For the value to which a state q maps x, you can construct the predicates:
q('x').equals(v) q('x')._in([n, m]) q('x')._in((n, m)) q('x') < v q('x') <= v
Here, v is either a constant or another measurable quantity (see above).
You can find the next call in time to the function f with:
q.next_call('f')
and treat the result as a call.
You can find the length of the value held in the variable x with:
q('x').length()
For a call t, you can measure the duration with:
t.duration()
and write predicates on this duration:
t.duration()._in([n, m]) t.duration()._in((n, m)) t.duration() < v t.duration() <= v
Here, v is either a constant or another measurable quantity (see above).
Currently arithmetic with measurable quantities with respect to constants is supported in a limited form:
t.duration() < v * n
where n is some constant of the same type of the measured quantity v. NB: here, multiplication must be on the right-hand side.
The states at either side of a call can be obtained with:
t.input(), t.result()
which gives a state object like any other. Hence, you could write something like:
t.input()('x') < t.result()('y')
The time between two states can be measured with:
timeBetween(q1, q2)
which can then be subject to a constraint by writing:
timeBetween(q1, q2)._in([n, m]) timeBetween(q1, q2) < n timeBetween(q1, q2) <= n
Here, n and m must be constants; VyPR does not yet support comparison of the result of timeBetween with other measurable quantities.
You can use boolean operators to combine predicates:
land(a1, a2, ..., a_n) lor(a_1, ..., a_n) lnot(a)
There is syntactic sugar for things like implication, which you can write as:
If(a).then(b)
You must wrap your final property in a lambda; VyPR will use this at runtime:
lambda q1, ..., qn : (...)
You can select points of interest based on states or calls with:
q = changes('x') t = calls('f')
If a selection predicate is given after the first one in the list, it must depend on the previous one:
Forall(q = changes('x')).Forall(t = calls('f', after='q'))...
The property to check at each point of interest is given by supplying the lambda to the Check method defined on the result of a chain of calls to Forall:
Forall(q1 = ...). ... .Forall(qn = ...).\ Check( lambda q1, ..., qn : (...) )