No edit summary |
|||
Line 71: | Line 71: | ||
With such a recursive function you can: | With such a recursive function you can: | ||
* apply the function to a given argument, e.g., parity(100) will give you 0 | |||
Computing the image of the function (<tt>parity[1..10]</tt>) or composing it with another function (<tt>([1,2] ; parity)</tt>) does not work yet. These work for non-recursive infinite functions, as described above. Future versions of ProB will probably allow these constructs for recursive functions as well. | Computing the image of the function (<tt>parity[1..10]</tt>) or composing it with another function (<tt>([1,2] ; parity)</tt>) does not work yet. These work for non-recursive infinite functions, as described above. Future versions of ProB will probably allow these constructs for recursive functions as well. | ||
There are the following further restrictions: | There are the following further restrictions: | ||
* ProB does not support mutual recursion yet | |||
* the function is not allowed to depend on other constants, unless those other constants can be valued in a deterministic way (i.e., ProB finds only one possible solution for them) |
Take the following function:
CONSTANTS parity PROPERTIES parity : (NATURAL --> {0,1}) & parity(0) = 0 & !x.(x:NATURAL => parity(x+1) = 1 - parity(x))
Here, ProB will complain that it cannot find a solution for parity. The reason is that parity is a function over an infinite domain, but ProB tries to represent the function as a finite set of maplets.
There are basically three solutions to this problem:
parity : (NAT --> {0,1}) & parity(0) = 0 & !x.(x:NAT & x<MAXINT => parity(x+1) = 1 - parity(x))
parity : (NATURAL --> {0,1}) & parity(0) = 0 & !x.(x:NATURAL1 => parity(x) = 1 - parity(x-1))
parity : INTEGER <-> INTEGER & parity = {0|->0} \/ %x.(x:NATURAL1|1-parity(x-1))
Note, you have to remove the check parity : (NATURAL --> {0,1}), as this will currently cause expansion of the recursive function. We describe this new scheme in more detail below.
parity : (NATURAL --> {0,1}) & parity = %x.(x:NATURAL|x mod 2)
You can experiment with those by using the Eval console of ProB, experimenting for example with the following complete machine. Note, you should use ProB 1.3.5-beta2 or higher.
MACHINE InfiniteParityFunction CONSTANTS parity PROPERTIES parity : NATURAL --> INTEGER & parity = %x.(x:NATURAL|x mod 2) VARIABLES c INVARIANT c: NATURAL INITIALISATION c:=0 OPERATIONS Inc = BEGIN c:=c+1 END; r <-- Parity = BEGIN r:= parity(c) END; r <-- ParityImage = BEGIN r:= parity[0..c] END; r <-- ParityHistory = BEGIN r:= (%i.(i:1..c+1|i-1) ; parity) END END
You may also want to look at the tutorial page on modeling infinite datatypes.
As of version 1.3.5-beta7 ProB now accepts recursively defined functions. For this:
Here is a full example:
MACHINE Parity ABSTRACT_CONSTANTS parity PROPERTIES parity : INTEGER <-> INTEGER & parity = {0|->0} \/ %x.(x:NATURAL1|1-parity(x-1)) END
With such a recursive function you can:
Computing the image of the function (parity[1..10]) or composing it with another function (([1,2] ; parity)) does not work yet. These work for non-recursive infinite functions, as described above. Future versions of ProB will probably allow these constructs for recursive functions as well.
There are the following further restrictions: