3

In z3 is it possible to declare a function that takes another function as an argument? For instance, this

(declare-fun foo ( ((Int) Bool) ) Int)

doesn't quite seem to work. Thanks.

JRR
  • 6,014
  • 6
  • 39
  • 59

2 Answers2

8

As Leonardo mentioned, SMT-Lib does not allow higher-order functions. This is not merely a syntactic restriction: Reasoning with higher-order functions is (generally) beyond what SMT solvers can deal with. (Although uninterpreted functions can be used in some special cases.)

If you do need to reason with higher-order functions, then interactive theorem provers are the main weapon of choice: Isabelle, HOL, Coq being some of the examples.

However, sometimes you want the higher-order functions not to reason about them, but rather merely to simplify programming tasks. SMT-Lib input language is not suitable for high-level programming that end-users typically need in practical situations. If that is your use case, then I'd recommend not using SMT-Lib directly, but rather working with a programming language that gives you access to Z3 (or other SMT solvers). There are several choices, depending on what host language is most suitable for your use case:

  • If you are a Python user, Z3Py that just shipped with Z3 4.0 is the way to go,
  • If you are a Scala user, then look into Scala^Z3.
  • If Haskell is your preferred language, then take a look at SBV.

Each binding has its own feature set, Z3Py probably being the most versatile since it's directly supported by the Z3 folks. (It also provides access to Z3 internals that remain inaccessible for the other choices, at least for the time being.)

alias
  • 28,120
  • 2
  • 23
  • 40
  • In theory, it's also possible to convert higher-order functions to SMT-LIB using [defunctionalization](https://en.wikipedia.org/wiki/Defunctionalization). – Anderson Green Nov 20 '19 at 17:54
  • Sure.. Defunctionalization is a great idea. But it requires you to know ahead of time exactly which functions can be used in a higher-order position; and is much more applicable in compilation and whole-program-analysis. When you want to *reason* about higher-order functions (like `map`/`filter` etc.), it doesn't really help. Try, for instance, proving `map f . map g = map (f . g)` equipped just with a definition of `map`. – alias Nov 20 '19 at 18:05
6

No, this is not possible. However, you can define a function that takes an array as an argument.

(declare-fun foo ((Array Int Bool)) Int)

You can use this trick to simulate high-order functions like the one in your question.

Here is an example: http://rise4fun.com/Z3/qsED

The Z3 guide contains more information about Z3 and SMT.

Leonardo de Moura
  • 21,065
  • 2
  • 47
  • 53