Zulip Chat Archive

Stream: Equational

Topic: Efficent representation of refutations


Joachim Breitner (Sep 27 2024 at 09:05):

Ah, I missed your message above, sorry!

Yes, something like that would help a lot. I think this ties into the wider question of what the “interface” between the individual lean files and the tools that scrape them for proven facts should be. Also see the topic #Equational > Where to store the ground truth of implications? and maybe open a new topic for this discussion.

Vlad Tsyrklevich (Sep 27 2024 at 09:07):

Just for future reference, here is something that I've been working on that does just this:

theorem multi_eq1 :  (G: Type) (_: Magma G), (Equation8 G  Equation99 G  Equation359 G  Equation411 G  Equation817 G  Equation1020 G  Equation1223 G  Equation1832 G  Equation3253 G  Equation3659 G  Equation3862 G  Equation4065 G)  ¬ Equation3 G  ¬ Equation23 G  ¬ Equation47 G  ¬ Equation151 G  ¬ Equation203 G  ¬ Equation255 G  ¬ Equation307 G  ¬ Equation614 G  ¬ Equation1426 G  ¬ Equation1629 G  ¬ Equation2035 G  ¬ Equation2238 G  ¬ Equation2441 G  ¬ Equation2644 G  ¬ Equation2847 G  ¬ Equation3050 G  ¬ Equation3456 G  ¬ Equation4380 G := by
  let hG : Magma Nat := {
    op := fun x y => if x = 0  y = 0 then 1 else x
  }
  use , hG

  apply And.intro
  focus
    repeat' apply And.intro
    all_goals {
      focus
        intro x;
        simp [hG];
        split_ifs <;> simp_all
    }

  repeat' apply And.intro
  all_goals {
    by_contra h
    specialize h 0
    dsimp [hG] at h
    linarith
  }

Joachim Breitner (Sep 27 2024 at 09:07):

Indeed, with this format every file could be a single theorem that doesn’t even mention the monoid, e.g.

theorems someFacts:  (G: Type) (_: Magma G), Equation1 G   Equation3 G  ¬ Equation3 G  ¬ Equation4 G

that can be proven in one go with by decide (or maybe by native_decide)

Notification Bot (Sep 27 2024 at 09:08):

3 messages were moved here from #Equational > Resolving >60% of cases with non-implications automatically by Joachim Breitner.

Joachim Breitner (Sep 27 2024 at 09:08):

Moved this to a new topic

Vlad Tsyrklevich (Sep 27 2024 at 09:08):

But yes, I agree it has to do with project structure. There is no way to maintain this project with 4700**2 theorems so I figured we must do something like this, and nicely, it works well with proving non-implies cases which are plentiful letting us cut the size of the project down

Joachim Breitner (Sep 27 2024 at 09:09):

We could even define a function

Refutations : List Nat  List Nat  Prop

for this theorem statement, which would make the lemma statement much shorter and easier to parse:

theorem multi_eq1 : Refutations [8,99,359] [2847,3050]

(for this we have to store the list of quations as a list, but that’s a good idea anyways, probably.)

Joachim Breitner (Sep 27 2024 at 09:16):

Actually, I like that. Let me implement that.

Vlad Tsyrklevich (Sep 27 2024 at 09:26):

There could be the same thing for implies, e.g. if EqA implies B,C,D,E, etc. I'm working on something like that as well at the moment. This does make introspecting on these proofs more difficult without a tool to print the list of implications/non-implications, but that's already a given with size of the search-space

Joachim Breitner (Sep 27 2024 at 09:37):

Not sure if this will scale to 4000 entries, but as a POC for the syntax this seems to work:

syntax (name := refutes)
  "Facts " ident " [" num,* "] " " [" num,* "]" : term

open Lean Elab in
macro_rules
  | `(Facts $G [$s:num, $ss,*] [$rs,*]) =>  do
    let i : Ident := mkIdent (.mkSimple s!"Equation{s.getNat}")
    `($i $G  Facts $G [$ss,*] [$rs,*])
  | `(Facts $G [$s:num] [$rs,*]) =>  do
    let i : Ident := mkIdent (.mkSimple s!"Equation{s.getNat}")
    `($i $G  Facts $G [] [$rs,*])
  | `(Facts $G [] [$r, $rs,*]) =>  do
    let i : Ident := mkIdent (.mkSimple s!"Equation{r.getNat}")
    `(¬ $i $G  Facts $G [] [$rs,*])
  | `(Facts $G [] [$r]) =>  do
    let i : Ident := mkIdent (.mkSimple s!"Equation{r.getNat}")
    `(¬ $i $G)

example (G : Type _) [Magma G] :
   Facts G [1, 2] [4, 5]  (Equation1 G  Equation2 G  ¬ Equation4 G  ¬ Equation5 G) :=
   Iff.rfl

Joachim Breitner (Sep 27 2024 at 09:48):

Ok, that runs into “deep recursion” :sweat_smile:

Vlad Tsyrklevich (Sep 27 2024 at 09:57):

Copying your code (getting rid of mathlib, Type* -> Type _) significantly improved my runtime for some brute force scripts locally. Running ~5k test theorems still takes almost a minute on my laptop though. It would be great if we could run these even faster, though as the graph gets filled out this will matter less.

Daniel Weber (Sep 27 2024 at 10:02):

Perhaps we could do something like docs#List.TFAE, but with two lists?

Joachim Breitner (Sep 27 2024 at 10:15):

Ok, this elaborates fast enough:

syntax "Facts " term:max " [" num,* "] " " [" num,* "]" : term

open Lean Meta Elab Term Tactic Parser.Term in
elab_rules : term | `(Facts $G [ $sats,* ] [ $refs,*]) => do
  let G  elabTerm G none
  let some u := ( getLevel G).dec | throwError "expected G to be a type"
  let inst  synthInstance (mkApp (mkConst ``Magma [u]) G)
  let s := sats.getElems.map fun s =>
    let n := .mkSimple s!"Equation{s.toNat}"
    mkApp2 (mkConst n [u]) G inst
  let r := refs.getElems.map fun s =>
    let n := .mkSimple s!"Equation{s.toNat}"
    mkApp (mkConst ``Not)  (mkApp2 (mkConst n [u]) G inst)
  let e := mkAndN (s ++ r).toList
  return e

Vlad Tsyrklevich (Sep 27 2024 at 10:17):

Perhaps you have the answer for what I'm hitting now then? I am hitting deep recursion now as well. Eq4 implies 1212 other equations by trivial rewriting, but trying to prove the conjunction of 1212 equations fails. I assume that it is better to prove them all at once then having individual implies. Example code here https://gist.github.com/vlad902/bec06a595758bf18569252177afef79a I'm not sure if your fix is different than what I am hitting.

Joachim Breitner (Sep 27 2024 at 10:24):

My file now looks like this, but with larger lists:

-- This is an example file, repesenting the generated files, but with shorter lists


import equational_theories.FinitePoly.Common
import equational_theories.FinitePoly.DecideBang
import equational_theories.FinitePoly.FactsSyntax

/-!
This file is generated from the following refutation as produced by
random generation of polynomials:
'(4 * x**2 + 4 * y**2 + 4 * x + 4 * y + 0 * x * y) % 5' (0, 42, 3252, 3318, 3341, 3455, 3521, 3544, 3861, 3914, 3963, 4064, 4117, 4166, 4282, 4357, 4379, 4397, 4404, 4434, 4441, 4481, 4530, 4543, 4634, 4676)

-/

set_option maxRecDepth 10000000
set_option maxHeartbeats 200000000
set_option synthInstance.maxHeartbeats 200000000


/-! The magma definition -/
def «FinitePoly 4 * x² + 4 * y² + 4 * x + 4 * y» : Magma (Fin 5) where
  op x y := 4 * x*x + 4 * y*y + 4 * x + 4 * y

/-! The facts -/
theorem «Facts from FinitePoly 4 * x² + 4 * y² + 4 * x + 4 * y» :
   (G : Type) (_ : Magma G), Facts G [1, 43, 3253] [2, 3, 4] := by
    refine Fin 5, «FinitePoly 4 * x² + 4 * y² + 4 * x + 4 * y», ?_⟩
    decide!

and I am getting

equational_theories/FinitePoly/Refutation0.lean:25:4: error: failed to synthesize

:confused:
(For smaller lists it works.)

Joachim Breitner (Sep 27 2024 at 10:29):

Progress using

    apply_rules only [And.intro]
    all_goals decide!

so that we don’t do the conjunction within decide

Joachim Breitner (Sep 27 2024 at 10:40):

Success! I had to write some meta code for this, but now one file is 28k, all files 3,5M, and each file takes 25s to process (which certainly can be sped up)


Last updated: May 02 2025 at 03:31 UTC