0

For example,

$ z3 -in
(declare-fun f (Int Real) Int)
(assert (= f f))
(check-sat)
sat

This is OK.

However, I'd like to qualify it by as?

$ z3 -in
(declare-fun f (Int Real) Int)
(assert (= (as f ???) (as f ???)))
(check-sat)
sat

What should I fill in ????

It must be a sort, but what sort should I use?

I have tried ((Int Real) Int) or (-> (Int Real) Int) or (_ (Int Real) Int), but none of them are correct.

Is it possible to declare a function sort in smtlib?

If there is impossible to declare a function sort, how to disambiguate f in the following program:

$ z3 -in
(declare-fun f (Int Real) Real)
(declare-fun f (Int Bool) Real)
(assert (= f f))
(error "line 3 column 11: ambiguous constant reference, more than one constant with the same sort, use a qualified expression (as <symbol> <sort>) to disambigua
te f")

Note that if I don’t use functions, it’s no problem:

$ z3 -in
(declare-fun f () Int)
(assert (= (as f Int) (as f Int)))
(check-sat)
sat

Thanks.

chansey
  • 1,266
  • 9
  • 20

1 Answers1

1

The annotation

(as f Int)

is correct, even though (as you noticed) is very confusing. This annotation does not necessarily mean f is Int. Rather, it means f results in an Int, so it could also be a function.

This is very confusing indeed, but it follows the standard http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2021-05-12.pdf, page 27:

Recall that every function symbol f is separately associated with one or more ranks, each specifying the sorts of f ’s arguments and result. To simplify sort checking, a function symbol in a term can be annotated with one of its result sorts σ. Such an annotated function symbol is a qualified identifier of the form (as f σ).

As indicated above in (as f σ), the type σ is the result sort of f.

Note also that solver support for these annotations is rather inconsistent. For a previous discussion on this, see https://github.com/Z3Prover/z3/issues/2135

alias
  • 28,120
  • 2
  • 23
  • 40
  • Very thanks for your answer. I have two questions: – chansey Sep 29 '21 at 15:16
  • (1) For the example of [the comment](https://github.com/Z3Prover/z3/issues/2135#issuecomment-477636435) , this issue seems fixed, because it is no problem in the latest release z3-4.8.12. However, my example still errors. ```(declare-fun f (Int Real) Int) (assert (= (as f Int) (as f Int))) (error "line 3 column 22: unknown constant fInt```. Do you think it is a z3 bug? – chansey Sep 29 '21 at 15:16
  • (2) If `f` should be annotated with its result sort, how to disambiguate the two `f`s with different params' sorts? Do you think it is a smtlib standard bug? – chansey Sep 29 '21 at 15:16
  • SMTLib is a first-order language. You *cannot* say `(= (as f Int) (as f Int))` to start with. The error from z3 might be a bit misleading, but it's essentially telling you that your "high-order" function comparison is invalid. To express what you've written, you'd use quantification, and make sure all applications of `f` are fully saturated. This is what it means to be "first-order." I don't think there's any bug anywhere, though I do agree the standard can be much more clear on its language. – alias Sep 29 '21 at 16:10
  • Thanks, so ideally in my 1st program `(assert (= f f))` should raise an error. Is that right? – chansey Sep 29 '21 at 16:13
  • 1
    Strictly speaking, yes. But z3 is being "liberal" here, and going beyond the SMTLib standard. If you pass it to cvc4, you'll see that it raises an error: `(error "Parse Error: a.smt2:2.15: Cannot apply equalty to functions unless --uf-ho is set.")` While solvers tend to be "standard-compliant," they extend it in various ways, not all of which is always compatible with each other. – alias Sep 29 '21 at 16:18