Zulip Chat Archive

Stream: Loom

Topic: Paper cuts


Shreyas Srinivas (Oct 30 2025 at 16:11):

I wrote the following #mwe which I think illustrates the kind of paper cuts I get stuck at for a while which I would think lean-auto could solve.

Shreyas Srinivas (Oct 30 2025 at 16:12):

import Auto

import Loom.MonadAlgebras.NonDetT.Extract
import Loom.MonadAlgebras.WP.Tactic
import Loom.MonadAlgebras.WP.DoNames'

import CaseStudies.Velvet.Std
import CaseStudies.TestingUtil

open PartialCorrectness DemonicChoice Lean.Elab.Term.DoNames

set_option auto.smt.trust true
set_option auto.smt true
set_option auto.smt.timeout 2
set_option auto.smt.solver.name "cvc5"

method swapIndex (mut a : Array Int) (i : ) (j : )
  return (a_swapped : Array Int)
  require i < a.size
  require j < a.size
  ensures a_swapped.size = a.size
  ensures  k : , k < a_swapped.size   k  i  k  j  a_swapped[k]! = a[k]!
  ensures a_swapped[i]! = a[j]!
  ensures a_swapped[j]! = a[i]!
  do
  let mut temp := a[i]!
  a[i] := a[j]!
  a[j] := temp
  return a

prove_correct swapIndex by
  loom_solve -- nothing done
  grind

Shreyas Srinivas (Oct 30 2025 at 16:12):

CC : @George Pîrlea

Shreyas Srinivas (Oct 30 2025 at 16:13):

why is loom_solve failing here?

Shreyas Srinivas (Oct 30 2025 at 16:19):

Further, there doesn't seem to be a way to name the requires so that I can use them for correct indexing (within the def)

Shreyas Srinivas (Oct 30 2025 at 16:35):

I did manage to solve this manually btw:

prove_correct swapIndex by
    loom_solve
    all_goals {
      simp [TArray.set, Array.setIfInBounds, require_1, require_2]
      try grind
    }

Vladimir Gladstein (Nov 07 2025 at 15:18):

@Shreyas Srinivas hey! Did you try running it with a new version of Loom? If not please run lake update. Now the default automation for Loom is grind.
Also, of you want to use SMT solver tactics , such as auto, please make sure that you have cvc5 installed on your PATH

Shreyas Srinivas (Nov 07 2025 at 15:19):

Hey I already have cvc5 on my path. I'll update now and try

Shreyas Srinivas (Nov 07 2025 at 15:20):

One thing I am missing is the ability to name and use the requires and ensures of a procedure call (inside another procedure). I understand that you are generating Anonymous names for these

Shreyas Srinivas (Nov 07 2025 at 15:23):

Example : if I call swapIndex from inside a (quicksort) partition function, I am not sure how I can get the postcondition for size out of the call

Vladimir Gladstein (Nov 07 2025 at 15:25):

Also it seems like you have a problem with your post-condition
when you write
ensures a_swapped[i]! = a[j]!
a_swapped refers to a modified array a. But in the same time, because you pass a as a mutable argument (mut a : Array Int), a in the post condition will be referring to a mutated version of a

Shreyas Srinivas (Nov 07 2025 at 15:26):

Initially I didn't have mut

Vladimir Gladstein (Nov 07 2025 at 15:26):

you can try the following spec

method swapIndex (mut a : Array Int) (i : ) (j : )
  return (a_swapped : Array Int)
  require i < a.size
  require j < a.size
  ensures a_swapped.size = a.size
  ensures  k : , k < a_swapped.size   k  i  k  j  a_swapped[k]! = a[k]!
  ensures a_swapped[i]! = aOld[j]!
  ensures a_swapped[j]! = aOld[i]!
  do
  let mut temp := a[i]!
  a[i] := a[j]!
  a[j] := temp
  return a

Vladimir Gladstein (Nov 07 2025 at 15:28):

Shreyas Srinivas said:

Initially I didn't have mut

If you don't have mut then you cannot modify a. So you either need to use mut and then refer to the old variable as aOld or remove mut and create a local mutable variable inside the method

Vladimir Gladstein (Nov 07 2025 at 15:30):

Shreyas Srinivas said:

One thing I am missing is the ability to name and use the requires and ensures of a procedure call (inside another procedure). I understand that you are generating Anonymous names for these

That's right, we indeed do not support this feature. If you could create a GitHub issue for it, we will add it in a course of the week.

Shreyas Srinivas (Nov 07 2025 at 15:30):

I noticed that TArray is gone with this update and we now just use normal Lean Arrays. This is a nice change

Shreyas Srinivas (Nov 07 2025 at 15:31):

Ah I didn't know one could access the old name as aOld. This helps

Vladimir Gladstein (Nov 07 2025 at 15:31):

Yes, I am planning to do a bunch of other cosmetics changes soon!

Vladimir Gladstein (Nov 07 2025 at 15:34):

Shreyas Srinivas said:

Ah I didn't know one could access the old name as aOld. This helps

You can refer to this documentation https://github.com/verse-lab/loom/blob/master/CaseStudies/Velvet/velvet_documentation.md


Last updated: Dec 20 2025 at 21:32 UTC