Zulip Chat Archive

Stream: new members

Topic: Help with aesop


john johnson (Dec 17 2024 at 19:22):

I have this code and I wanted to prove the last theorem using aesop, and even though the proof consists of only succesive applications of Order.trans, aesop is only able to prove it after I insert the first apply manually and I'm not sure I understand why considering it's able to provide the remaining steps. What am I doing wrong?

import Mathlib.Tactic

def _xor (p q : Prop) := ¬(p  q)

infix:50 " ∨+ " => _xor

class Order (X : Type) where
  S : X -> X -> Prop
  tri : x y : X, (x = y) ∨+ (S x y) ∨+ (S y x)
  trans : {x y z: X}, (S x y) -> (S y z) -> (S x z)

instance (X : Type) [Order X] : LT X where
  lt := fun x y => Order.S x y

instance (X : Type) [Order X] : LE X where
  le := fun x y => Order.S x y  x = y

add_aesop_rules unsafe apply 50% [Order.trans]

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  apply Order.trans
  aesop
  aesop

Kevin Buzzard (Dec 17 2024 at 19:23):

Try add_aesop_rules safe forward Order.trans instead?

john johnson (Dec 17 2024 at 19:27):

It didn't work unfortunately, I still get
tactic 'aesop' failed, made no progress

Kevin Buzzard (Dec 17 2024 at 19:29):

OK now at a computer, I'll take a look. Your code doesn't compile for me (with set_option autoImplicit false) so you might want to think about fixing that first, this usually means that your code doesn't say what you think it says.

Kevin Buzzard (Dec 17 2024 at 19:35):

The autoimplicit issue is with Order.tri so it doesn't affect your question. I believe that the reason aesop isn't doing what you want it to do is that it can't see through < to get Order.S.

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  -- statement about `<`
  apply Order.trans
  -- statements about `S`, so `aesop` now works
  ...

Here's an example of how to fix it:

lemma Order.lt_trans (X : Type) [Order X] (x y z : X) (h1 : x < y) (h2 : y < z) : x < z :=
  Order.trans h1 h2

-- this is the lemma `aesop` actually needs
add_aesop_rules safe forward Order.lt_trans

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  aesop

Lean doesn't just unfold things willy-nilly, this would cause chaos in general. So although you taught Aesop about Order.trans, it still didn't know a thing about <.

Kevin Buzzard (Dec 17 2024 at 19:38):

With the set_option autoImplicit true footgun on (I have this off by default on all my projects), your Order.tri is

Order.tri {X : Type} [self : Order X] {y x : X} : ( (x y : X), (x = y) ∨+ Order.S x y) ∨+ Order.S y x

which is syntactically equivalent to

Order.tri {X : Type} [self : Order X] {y x : X} : ( (a b : X), (a = b) ∨+ Order.S a b) ∨+ Order.S y x

which I'm sure is not at all what you want.

john johnson (Dec 17 2024 at 19:49):

I see, I was thinking aesop would be able to find this proof since it only uses rules that it knows about

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  apply Order.trans
  apply Order.trans h1 h2
  exact h3

Could there still be a way to make it find this proof instead or any proof using Order.trans only?

Kevin Buzzard (Dec 17 2024 at 19:57):

Your proof is abusing definitional equality, so is not good style. I'm not an expert in this sort of thing, but my instinct is that if Lean sees a hypothesis x < y and it has a lemma which has hypothesis Order.S x y then no way will you get it to apply that lemma, because any system which allows the unfolding of x < y is a system which will immediately grind to a halt the moment it sees the kind of monstrosities which we've constructed in mathlib.

One approach if you're desperate to make this sort of thing work is to use notation x < y to mean Order.S x y, instead of a typeclass, because Lean will happily look through the definition of notation. It will also look through reducible definitions, but LT is not your definition so you don't get to set its reducibility level.

notation x "<" y => Order.S x y -- this might have unfortunate consequences elsewhere

add_aesop_rules unsafe apply 50% [Order.trans]

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  aesop -- works, because x < y is now *syntactically* Order.S x y

Kevin Buzzard (Dec 17 2024 at 20:07):

Another approach is to teach the system that x < y <-> S x y, like this:

instance (X : Type) [Order X] : LT X where
  lt := fun x y => Order.S x y

@[simp]
lemma Order.lt_def {X : Type} [Order X] (x y : X) : x < y  Order.S x y := by rfl

add_aesop_rules safe forward Order.trans

theorem test (X : Type) [Order X] (x y z w: X) (h1 : x < y) (h2 : y < z) (h3 : z < w): x < w := by
  aesop

Kevin Buzzard (Dec 17 2024 at 20:08):

Be warned now though that the simplifier will constantly replace x < y with S x y, which may or may not be what you want.

john johnson (Dec 17 2024 at 20:20):

I like this second approach, my only problem is that so far it seemed harder to figure out what aesop wants to complete a proof than to just do the proof manually, and I was hoping I could use to spend less time proving "obvious" things. Or maybe I just don't know how to use it properly

Kevin Buzzard (Dec 17 2024 at 20:24):

My initial mental model of aesop was that it would just do everything automatically, but more recently I've come to understand that it needs training. Understanding that x < y is syntactically (i.e. notation for) LT.lt x y but only definitionally Order.S x y is I guess important for your situation here, and I guess tagging lt_def @[simp] is solving that problem. aesop is not going to use lemmas it's not been told about though. One approach used in mathlib is the aesop_cat approach, where a bespoke trained version of aesop is used to prove results in category theory.

john johnson (Dec 17 2024 at 20:32):

Maybe one last thing, is there a way to make aesop use lemmas without having to mention them explicitly? For example passing an entire file and having it look for things that could be useful?

Kevin Buzzard (Dec 17 2024 at 20:37):

I'm afraid that's beyond my pay grade, I'm but a lowly mathematician. Hopefully someone else will chime in.

john johnson (Dec 17 2024 at 20:40):

No problem, thanks for the help :smile:

Mario Carneiro (Dec 17 2024 at 20:41):

It depends on what you mean by "mentioning them explicitly". The proof above is a plain call to aesop that does not mention any lemmas, but you have to tag lemmas first before that will work

Mario Carneiro (Dec 17 2024 at 20:42):

it's similar to simp in that regard

Mario Carneiro (Dec 17 2024 at 20:42):

it does not crawl the library looking for lemmas

Mario Carneiro (Dec 17 2024 at 20:42):

the only tactics I'm aware of that do that are exact? and apply?

john johnson (Dec 17 2024 at 20:52):

I understand, I was wondering if there is a way to make it behave like exact? in that sense or maybe an alternative with that behaviour


Last updated: May 02 2025 at 03:31 UTC