I am trying to specify a concrete formula in Z3-Python.
Exists i::Integer s.t. (0<=i<|arr|) & (avg(arr)+t<arr[i])
This means: whether there is a position i::0<i<|arr|
in the array whose value a[i]
is greater than the average of the array avg(arr)
plus a given threshold t
.
I posted at Theory of arrays in Z3: (1) model is difficult to understand, (2) do not know how to implement functions and (3) difference with sequences how I approached this using arrays. Among others, I need to define a function for getting the average
of the array, and another one for its length
; however, approaching this problem using Z3's arrays does not seem to be a good idea.
Thus, I 'emulated' it using sequences:
t = Int('t')
avg_seq = Int('avg_seq')
i = Int('i')
seq = Const('seq', SeqSort(IntSort()))
phi = Exists(i, And([(And(2<t, t<10)), (And(0 <= i, i< Length(seq))), ((t+avg_seq<seq[i]))]))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
Where one model I got is the following:
sat
[avg_seq = 7715,
t = 3,
seq = Unit(7719),
seq.nth_u = [else -> 4]]
As you can see, I solved the problem of how to calculate Length
, since it is a primitive in Z3.
However, how can I create an average
function? Is there any primitives for it? I guess there is not, so I planned to create a recursive version of it. The pseudo-code of my idea is as follows:
Avg(Seq) = Sum(Seq)/Length(Seq)
Sum(Seq) = Head(Seq) + Sum(Tail(Seq))
Is this idea right? How can I implement this? I was recommended to read the example of RecAddDefinition
at Converting `appendo` relation from smt2 to python, but I feel pretty lost, specially when I see constructions like Const
.
I also have one extra doubt: I understood that when defininf a Exists(i, ...)
, the top-level declaration of i
is unused; however, if I do not declare it, I receive the error: name 'i' is not defined
.