1
$\begingroup$

I am trying to get some experience with using Lean 4 and write some functional programs that I can use for my daily work. One feature I'd like to have is to interface Lean 4 with external C/C++ code to do heavy computations such as matrix multiplication. Note: I just need the computation, not the theorem proving capabilities of lean for this exercise.

Lean 4's FFI documentation said that is unstable upfront:

NOTE: The current interface was designed for internal use in Lean and should be considered unstable. It will be refined and extended in the future.

But it's already 12 versions since Lean 4' initial release, and I guess it's not a good idea to wait until the FFI is eventually stable. And I don't mind refining my program later on when the FFI is refined/extended. Hence the question here.

Can the Lean4 FFI (as of 4.12) be used to interface with external C++ code for matrix operations? In particular, does it support passing dense or sparse matrices/arrays between Lean and C++?

Are there examples/tutorials for doing this kind of work?

$\endgroup$
3
  • $\begingroup$ The answer is yes, but there may be some subtitles as to what you want. Do you want to replace the current matrix multiplication in mathlib with an external implementation? Mathlib isn’t particularly suited for computable code so depending on the matrix definition, it may be slow or impossible to directly work with. (I think just slow.). Similarly, you can’t compute in Lean with the mathlib type Real even via FFI. You can compute with arrays of machine types like Float, Int64, UInt64 and easily do FFI. Nat and Int may be more subtle since they are unbounded numbers. $\endgroup$
    – Jason Rute
    Commented Nov 24 at 13:15
  • $\begingroup$ @JasonRute. Thanks. I'd like to compute with primitive machine types such as Float. The goal is to just to do some regular programming using Lean as a upgraded FP language (as a learning exercise). Hopefully, this will be enough motivation for exploring lean programming and the new things with dependent types. $\endgroup$
    – tinlyx
    Commented Nov 24 at 15:30
  • $\begingroup$ Also there's github.com/DSLstandard/… and github.com/tydeu/lean4-alloy, though they are for C. But at this point I would think you'd maybe need to go through a C wrapper to use something C++, but idk really. I would also want to know. $\endgroup$
    – noncom
    Commented 19 hours ago

2 Answers 2

1
$\begingroup$

I don't think Lean's FFI is well documented, but there is a short documentation (which you already mentioned) and a guide that someone wrote.

Also, for this particular use case, check out SciLean. I don't know a lot about it, or even if it uses FFI, but it seems related.

Lean has support for (dense) machine-native arrays in Array, so I think you won't find connecting them with the FFI more painful than any other FFI use case. (I think you would have to implement sparse arrays in Lean yourself or see if they are in SciLean.)

But also note that working with arrays in place in Lean is a bit subtle. You have to use destructive updates, where you only have one reference to the array at a time (like in Rust, but without the borrow checker). That way, Lean won't copy the array, but instead modify it in place. (Unless you want to copy the array like is common for most operations in say Python's numpy library.)

$\endgroup$
2
  • $\begingroup$ Thanks! The guide is great. But I didn't find an example of using Array (it says that it may be added in the future). Do you have a reference code? I am mostly interested in the numpy approach that copies the array/matrix. Also, I'd like to know how to do this for lists. All I need is to pass (by copying) arrays/matrices of Float's back and forth between lean and c++. $\endgroup$
    – tinlyx
    Commented Nov 25 at 7:25
  • $\begingroup$ Another point is that I want to be as close to lean's math functions as possible. That is, I wanted to avoid the IO monad or its like, and write a "pure" FFI function that, e.g. multiplies two matrices and return one as if these matrices are numbers. In Haskell, there is unsafePerformIO (stackoverflow.com/a/10530919). I was wondering if there are similar facilities in lean. $\endgroup$
    – tinlyx
    Commented Nov 25 at 7:29
1
$\begingroup$

I have a proof of concept for binding c++ library Eigen to Lean, EigenLean. It has examples for dense and sparse matrices.

Unfortunately, lake still does not have a proper support for building ffi with c++ so you have to call a custom command lake run buildEigen before lake build.

examples/dense.lean

  let A : Matrix 2 2 := ⟨FloatArray.mk #[2,1,1,2], by native_decide⟩
  let b : Matrix 2 1 := ⟨FloatArray.mk #[1,1], by native_decide⟩

  IO.println s!"A  = {A}"
  IO.println s!"b  = {b}"
  IO.println s!"A⁻¹ = {A.ldlt.solve b}"

examples/sparse.lean

  let entries : Array (Triplet 2 2) := (#[(0,0,2.0), (1,0,1.0), (1,1,2.0), (0,1, 1.0)] : Array (Nat×Nat×Float))
  let A := SparseMatrix.mk entries
  let b : Matrix 2 1 := ⟨FloatArray.mk #[1,1], by native_decide⟩

  IO.println s!"A  = {A.toDense}"
  IO.println s!"b  = {b}"
  IO.println s!"A⁻¹ = {A.simplicialLLT.solve b}"

At some point it will be integrated in SciLean but I still do not know how to make the build robust across all platforms.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.