Zulip Chat Archive

Stream: lean4

Topic: isDefEq deterministic timeout


Jovan Gerbscheid (Oct 29 2023 at 09:30):

I ran into a problem where isDefEq does a deterministic time-out, when it should fail. Here is a minimal example:

open Lean Meta Expr
#eval show MetaM _ from do
  let ringNat  mkFreshExprMVar (Expr.app (.const ``StrictOrderedRing [.zero]) (.const `Nat []))
  let lhs := .app
    (.app (.const `Filter.atTop [.zero]) (.const `Nat []))
    (.app
      (.app (.const `PartialOrder.toPreorder [.zero]) (.const `Nat []))
      (.app
        (.app
          (.const `StrictOrderedSemiring.toPartialOrder [.zero])
          (.const `Nat []))
        (.const
          `Nat.strictOrderedSemiring
          [])))
  let rhs := .app
    (.app (.const `Filter.atTop [.zero]) (.const `Nat []))
    (.app
      (.app (.const `PartialOrder.toPreorder [.zero]) (.const `Nat []))
      (.app
        (.app (.const `StrictOrderedRing.toPartialOrder [.zero]) (.const `Nat []))
              ringNat))
  logInfo m! "{← isDefEq lhs rhs}"

which gives

(deterministic) timeout at 'isDefEq', maximum number of heartbeats (200000) has been reached (use 'set_option maxHeartbeats <num>' to set the limit)

Clearly, Nat is not a ring, so it should fail the unification.

Mauricio Collares (Oct 29 2023 at 10:20):

#mwe?

Jovan Gerbscheid (Oct 29 2023 at 12:35):

Ah, sorry. Here it is:

import Lean
import Mathlib

open Lean Meta Expr
#eval show MetaM Bool from do
  let ringNat  mkFreshExprMVar (Expr.app (.const ``StrictOrderedRing [.zero]) (.const `Nat []))
  let lhs := .app
    (.app (.const `Filter.atTop [.zero]) (.const `Nat []))
    (.app
      (.app (.const `PartialOrder.toPreorder [.zero]) (.const `Nat []))
      (.app
        (.app
          (.const `StrictOrderedSemiring.toPartialOrder [.zero])
          (.const `Nat []))
        (.const
          `Nat.strictOrderedSemiring
          [])))
  let rhs := .app
    (.app (.const `Filter.atTop [.zero]) (.const `Nat []))
    (.app
      (.app (.const `PartialOrder.toPreorder [.zero]) (.const `Nat []))
      (.app
        (.app (.const `StrictOrderedRing.toPartialOrder [.zero]) (.const `Nat []))
              ringNat))
  isDefEq lhs rhs

Gareth Ma (Oct 29 2023 at 14:33):

:joy:

Mauricio Collares (Oct 29 2023 at 14:37):

(deleted)

Mauricio Collares (Oct 29 2023 at 14:39):

You can type set_option trace.Meta.synthInstance true and set_option trace.profiler true to see what Lean is trying.

Mauricio Collares (Oct 29 2023 at 14:48):

(deleted)

Jovan Gerbscheid (Oct 29 2023 at 19:31):

I tried using set_option maxHeartbeats 1000000, and now after almost a minute, it successfully returns false. set_option trace.profiler true indeed shows what Lean is trying, but it doesn't help me much. I suppose I shouldn't trust that all definitions in Mathlib are handled well by isDefEq. Instead, is there a good way to limit the run time taken by isDefEq? I'm working on an interactive program, so I need it to run near instantaneously.

Gareth Ma (Oct 29 2023 at 22:22):

Instead, is there a good way to limit the run time taken by isDefEq?

Isn't that what maxHeartbeats does?

Kyle Miller (Oct 29 2023 at 22:31):

It looks like Aesop wanted a similar thing, so there's docs#Aesop.withMaxHeartbeats to limit a sub-computation. It doesn't let you know if the result failed specifically due to the heartbeat limit however.

Jovan Gerbscheid (Oct 30 2023 at 01:15):

Kyle Miller said:

It looks like Aesop wanted a similar thing, so there's docs#Aesop.withMaxHeartbeats to limit a sub-computation. It doesn't let you know if the result failed specifically due to the heartbeat limit however.

Thanks, that should do the job.

Jannis Limperg (Oct 30 2023 at 13:06):

There is also the extremely hacky docs#Lean.Exception.isMaxHeartbeat for figuring out whether an exception is due to a deterministic timeout.


Last updated: Dec 20 2023 at 11:08 UTC