Zulip Chat Archive

Stream: new members

Topic: Experimenting with a new tactic - unknown tag


Michael Bucko (Dec 16 2024 at 15:46):

I am writing a tactic build_connect_line_no_hashing_direct_construction and somehow always getting unknown attribute [build_connect_line_no_hashing_direct_construction], even though the attribute registration code goes first.

What am I doing wrong?

import Lean
import Mathlib

open Lean Meta Elab Tactic

initialize buildAttr : ParametricAttribute Unit 
  registerParametricAttribute {
    name := `build
    descr := "Build by connecting two concepts"
    getParam := fun _ _ => pure ()
  }

elab "build_connect_line_no_hashing_direct_construction" : tactic => do
  let env  getEnv
  let entries := buildAttr.ext.getState env
  let decls := entries.toList.map (·.1)
  let goal  getMainGoal
  let axiomsTypes  decls.mapM fun decl => do
    let cinfo  liftMetaM (getConstInfo decl)
    pure cinfo.type
  if axiomsTypes.isEmpty then return
  let allAxioms  axiomsTypes.foldlM (init := axiomsTypes.head!) fun acc newTy => do
    let accType  liftMetaM (whnf acc)
    let newType  liftMetaM (whnf newTy)
    liftMetaM (mkAppM ``And #[accType, newType])
  let placeholderProp := mkForall Name.anonymous BinderInfo.default (mkConst ``False) (mkConst ``False)
  liftMetaM (goal.assign (mkForall Name.anonymous BinderInfo.default allAxioms placeholderProp))
  let goals  getGoals
  match goals with
  | [g] => do
    let (_, g1)  liftMetaM (g.intro1)
    let (_, g2)  liftMetaM (g1.intro1)
    let g2Type  liftMetaM (g2.getType)
    let sorryExpr  liftMetaM (mkSorry g2Type true)
    let newGoals  liftMetaM (g2.apply sorryExpr)
    setGoals newGoals
  | _ => pure ()

def is_k_almost_prime (k n : Nat) : Bool :=
  n > 1 && n.factorization.sum (fun _ multiplicity => multiplicity) == k

def is_k_almost_prime_prop (k n : Nat) : Prop :=
  is_k_almost_prime k n = true

noncomputable def nth_k_almost_prime (k i : Nat) : Nat :=
  Classical.epsilon (fun n =>
    is_k_almost_prime_prop k n 
    (((List.range (n+1)).filter (is_k_almost_prime k)).length = i+1)
  )

noncomputable def almost_prime_table (k i : Nat) : Nat :=
  nth_k_almost_prime (k+1) i

def col_has_power (k power : Nat) : Prop :=
   i, almost_prime_table k i = power

noncomputable instance (k power : Nat) : Decidable (col_has_power k power) :=
  Classical.propDecidable _

noncomputable def find_power_index (k power : Nat) : Option Nat :=
  if h : col_has_power k power then
    some (Nat.find h)
  else
    none

noncomputable def red_diamond_sequence_column (k : Nat) : Set Nat :=
  let currentPower := 3^(k+1)
  let nextPower := 3^(k+2)
  match find_power_index (k+1) nextPower with
  | some r => { n | n  currentPower   i, i < r  almost_prime_table k i = n }
  | none   => { n | n  currentPower   i, almost_prime_table k i = n }

@[build_connect_line_no_hashing_direct_construction]
axiom red_diamond_conjecture_infinite :  k,
  ( r, find_power_index (k+1) (3^(k+2)) = some r 
    almost_prime_table (k+1) r = 3^(k+2) 
    ( i, i < r  almost_prime_table k i  red_diamond_sequence_column k))

@[build_connect_line_no_hashing_direct_construction]
axiom beal_conjecture :
   x y z : , x > 2  y > 2  z > 2 
   A B C : , A > 0  B > 0  C > 0 
  A ^ x + B ^ y = C ^ z 
  Finset.gcd {A, B, C} id > 1

@[build_connect_line_no_hashing_direct_construction]
axiom abc_conjecture :
   (ε : ) (_ : 0 < ε),  (K : ),
     (a b c : ), a > 0  b > 0  c > 0 
    a + b = c 
    gcd a b = 1 
    (c : ) < K * Real.rpow ((Nat.primeFactorsList (a * b * c)).prod) (1 + ε)

Damiano Testa (Dec 16 2024 at 21:46):

I have not tried to see if this is the case, but attributes can only be used in a file in which their definition is imported: the file that defines an attribute should not have access to the attribute itself.

Michael Bucko (Dec 17 2024 at 15:38):

(Thank you @Damiano Testa . Testing this -- but having some problems with the toolchain, so it's taking some time)

Michael Bucko (Dec 17 2024 at 19:27):

@Damiano Testa Divided the code into two files (below), but I am still getting the same thing (nonetheless, your point is still good, and I was not aware of that).

import Lean
import Mathlib
import build_connect_line_no_hashing_direct_construction

open Lean Meta Elab Tactic

@[build_connect_line_no_hashing_direct_construction]
axiom red_diamond_conjecture_infinite :  k,
  ( r, find_power_index (k+1) (3^(k+2)) = some r 
    almost_prime_table (k+1) r = 3^(k+2) 
    ( i, i < r  almost_prime_table k i  red_diamond_sequence_column k))

@[build_connect_line_no_hashing_direct_construction]
axiom beal_conjecture :
   x y z : , x > 2  y > 2  z > 2 
   A B C : , A > 0  B > 0  C > 0 
  A ^ x + B ^ y = C ^ z 
  Finset.gcd {A, B, C} id > 1

@[build_connect_line_no_hashing_direct_construction]
axiom abc_conjecture :
   (ε : ) (_ : 0 < ε),  (K : ),
     (a b c : ), a > 0  b > 0  c > 0 
    a + b = c 
    gcd a b = 1 
    (c : ) < K * Real.rpow ((Nat.primeFactorsList (a * b * c)).prod) (1 + ε)

and build_connect_line_no_hashing_direct_construction.lean

import Lean
import Mathlib

open Lean Meta Elab Tactic

initialize buildAttr : ParametricAttribute Unit 
  registerParametricAttribute {
    name := `build
    descr := "Build by connecting two concepts"
    getParam := fun _ _ => pure ()
  }

elab "build_connect_line_no_hashing_direct_construction" : tactic => do
  let env  getEnv
  let entries := buildAttr.ext.getState env
  let decls := entries.toList.map (·.1)
  let goal  getMainGoal
  let axiomsTypes  decls.mapM fun decl => do
    let cinfo  liftMetaM (getConstInfo decl)
    pure cinfo.type
  if axiomsTypes.isEmpty then return
  let allAxioms  axiomsTypes.foldlM (init := axiomsTypes.head!) fun acc newTy => do
    let accType  liftMetaM (whnf acc)
    let newType  liftMetaM (whnf newTy)
    liftMetaM (mkAppM ``And #[accType, newType])
  let placeholderProp := mkForall Name.anonymous BinderInfo.default (mkConst ``False) (mkConst ``False)
  liftMetaM (goal.assign (mkForall Name.anonymous BinderInfo.default allAxioms placeholderProp))
  let goals  getGoals
  match goals with
  | [g] => do
    let (_, g1)  liftMetaM (g.intro1)
    let (_, g2)  liftMetaM (g1.intro1)
    let g2Type  liftMetaM (g2.getType)
    let sorryExpr  liftMetaM (mkSorry g2Type true)
    let newGoals  liftMetaM (g2.apply sorryExpr)
    setGoals newGoals
  | _ => pure ()

Last updated: May 02 2025 at 03:31 UTC