Zulip Chat Archive

Stream: Is there code for X?

Topic: Calculating Floating Point Array with External Executable


Paul Wintz (Aug 01 2023 at 01:21):

Within Lean, I would like to call an external tool (such as a C++ executable or library) to calculate an array of floating-point values, then use the resulting values to complete a proof. In particular, I want to take a given polynomial and use an external tool to try to construct a sum-of-squares representation of the polynomial---or show that it cannot be done.

Has anybody done this sort of thing before? I saw the page Foreign Function Interface in the manual, which says the interface for calling external libraries is unstable. Are there any alternatives?

Paul Wintz (Aug 01 2023 at 06:42):

I found this paper from 2017 that does something similar to what I want, except using Mathematica instead of a C++ program.

Eric Wieser (Aug 01 2023 at 08:23):

"Unstable" here means "the API might change in future versions of Lean" not "the API is unreliable"

Eric Wieser (Aug 01 2023 at 08:26):

If you don't like the sound of that, having Lean call your program as a subprocess is an option

Paul Wintz (Aug 01 2023 at 08:55):

How do you call a program as a subprocess? I haven't come across that in the documentation.

Eric Wieser (Aug 01 2023 at 09:16):

docs#IO.Process.run is one way

Paul Wintz (Aug 02 2023 at 07:37):

That looks like what I need. Thanks!

Paul Wintz (Aug 09 2023 at 20:38):

@Eric Wieser, are there any examples that use IO.Process.run that I could see?

Paul Wintz (Aug 10 2023 at 18:41):

Here is what I have tried for running a process without using any returned values. It doesn't seem to actually execute the given command, though (the file ~/mytestfilefromlean.txt is not created).

def args : IO.Process.SpawnArgs where
  cmd := "touch"
  args : Array String := #["~/mytestfilefromlean.txt"]

#check IO.Process.run args

Using #check was just a shot in the dark. What is the right way to execute the process call?

Paul Wintz (Aug 10 2023 at 18:45):

My inevitable follow questions will be how to access the output from the process (presumably as a String?)

Eric Wieser (Aug 10 2023 at 18:47):

Does #eval work?

Paul Wintz (Aug 10 2023 at 20:49):

When I replace #check with #eval, I get an error that says,

no such file or directory (error code: 2)

I thought maybe this has something to do with not finding my home directory using the ~ alias, but the changing the cmd to "echo" produces the same error:

def args : IO.Process.SpawnArgs where
  cmd := "echo"
  args : Array String := #["Hello, world"]

#eval IO.Process.run args

Eric Wieser (Aug 10 2023 at 20:59):

I'm not sure that echo is a real command, isn't it just a shell built-in?

Alex J. Best (Aug 11 2023 at 13:13):

Echo is a real command for me (ubuntu) and the above code produces "Hello, world\n"

Paul Wintz (Aug 14 2023 at 23:34):

Got it: the problem probably is that I'm on Windows and echo is not available (I typically use Git-Bash so I forget that Windows commands are different). The following code works:

def args : IO.Process.SpawnArgs where
  cmd := "python"
  args : Array String := #["--version"]

#eval IO.Process.run args

Last updated: Dec 20 2023 at 11:08 UTC