Some system-defined predicates are polymorphic; that is, they act as procedures with different parameter types and modes in different situations. This section describes the legal type casts, the automatic coercions done by FormulaOne, and the characteristics of all the polymorphic predicates.
This means not just that the shape of the term is the same, but that the term' is a member of the subset of U corresponding to type; for instance, the term R(3.14159) is not a member of the type [2..4] because it does not stand for an integer in that range.
When the type cast term is defined, it stands (computationally) for the given term, represented in the representation of the given type. When the type cast term is undefined, the formula containing it is false (computationally, it fails causing a backtrack).Terms are mapped into elements of the type U as follows, a' stands for the mapping of a into the universal type U, etc.
Most of the cases in which this can happen have the property that type1 is wider than type2 - that is, that all the elements of type2 are contained in type1 - or vice versa. These cases are summarized in Type coercion table.
A widening coercion (for instance, from I to L or from any type to U) always succeeds; but a narrowing coercion can sometimes fail. The cases in which a narrowing coercion will succeed are those in which the term passes the test shown in the third column of the Type coercion table.
One other class of coercion not shown in the table is done: between subrange terms and I, L, or other subrange terms. In this kind of coercion, the value is simply checked to see if it is in the proper range.As with type casts, if a type coercion fails, it causes the formula containing the coerced term to fail.
Type coercion table. T represents any type.| Wider Type | Narrower Type | Test |
| U | T | Fits T? |
| [0..]->T | [0..n]->T | Upper bound n? |
| [0..n]->T | [0..n]->>T | All elements different? |
| R | L | Unlimited Integer |
| R | I | Integer form -231 to 231-1? |
| L | I | Integer from -231 to 231-1? |
These declarations are really pseudo-code, only to indicate approximately how FormulaOne treats the predicates.
Note: You need FormulaOne compiler release 41C or later for _AllDifferent, _AllAscending, _AllDescending, _Ascending, _Descendig.proc Print(xl :< Tl, ..., xn :< Tn)The type information is used by Print to determine how it should print the arguments - as strings, arrays, tuples, etc.
proc Len(a :< [0..n]->T, len :> I)
pred Len(a::[0..n]->T, len :> I)
proc Len(a :< [0..]->T, len :> I)
pred Len{a::[0..]->T, len :> I)
proc Len(s :< S, len :> I)
proc Len(l :< list T, len :> I)
pred Len(l :: list T, len :: I)
With arrays, Len returns the number of elements in the array (recall that flexible arrays ave a known number of elements at run time, and that while the elements of symbolic arrays may be unknown, the number of elements is always known). With strings, Len returns the length of the string. With lists, Len returns the number of elements in the list, not counting Nil. The symbolic list predicate form of Len behaves exactly as the following predicate, for every T:
pred Len(l :: list T, len :: I) iff
len = 0 & l = Nil |
len > 0 &
l = (_,t) & Lent(t, len-1)
proc Append(s1 :< S, s2 :< S, s_out :> S) proc Append(l1 :< list T, l2 :< list T, l_out :> list T) pred Append(l1 :: list T, l2 :: list T, l__out :: list T)Append returns the string or list consisting of the concatenation of the first two parameters in its call. The last version of Append behaves exactly as the following predicate, for every T:
pred Append (l1 :: list T, l2 :: list T, l_out :: list T) iff
l1 = Nil & l_out = l2 | l1 = (h, t) &
l_out = (h, l_aux)
& Append(t, l2, l aux)
proc In(x :< T, l :< list T) pred In(x :> T, l :< list T) pred In(x :: T, l :: list T) proc In(pat :< S, s :< S)The first list predicate form has the effect of testing the membership of x in l. The second form assigns to x each of the members of l on backtracking. The third form behaves exactly as the following predicate, for every T:
pred In(x :: T, l :: list T) iff
l = (h, t) & ( h = x | In(x, t))
The form with string-typed arguments is a pattern matching form, which matches the wild-card character "*" to any sequence of text (possibly empty), and any other characters to themselves. For instance, all the following formulas should be true:
'*a*a' in 'lava'
'*a*a' in 'ada'
'*a*a' in 'llama' \
'*ula*' in 'FormulaOne'
'*log*' in 'Prolog'
proc Dupl(n :< I, x :< T, array :> [0..]->T )It has the effect of putting into array, an array constructed of n copies of the value x.
pred _AllDifferent(x1::T, x2::T, x3::T, ..., xn::T)The _AllDifferent predicate places n(n-1)/2 binary constraints on n variables, ensuring no two variables can have the same value.
pred _AllDifferent(x1::T, x2::T, x3::T, ..., xn::T) iff
x1 <> x2 & x1 <> x3 & ... x1 <> xn &
x2 <> x3 & ... x2 <> xn &
x3 <> xn
For example, the following query
all x::[1..2] & y::[1..4] & z ::I[1..2] & _AllDifferent(x,y,z)
will generate the following solutions:
x = 2
y = 3
z = 1
___ Solution: 1 __________________________________
x = 2
y = 4
z = 1
___ Solution: 2 __________________________________
x = 1
y = 3
z = 2
___ Solution: 3 __________________________________
x = 1
y = 4
z = 2
___ Solution: 4 __________________________________
Number of solutions: 4 Number of backtracks: 0
Elapsed time: 00:00:00
pred _AllAscending(x1::T, x2::T, x3::T, ..., xn::T) iff
x1 < x2 & x1 < x3 & ... x1 < xn
For example, the following query
all x::[1..2] & y::[1..4] & z ::I[1..4] & _AllAscending(x,y,z)will generate the following solutions:
x = 1 y = 2 z = 3 ___ Solution: 1 __________________________________ x = 1 y = 2 z = 4 ___ Solution: 2 __________________________________ x = 1 y = 3 z = 4 ___ Solution: 3 __________________________________ x = 2 y = 3 z = 4 ___ Solution: 4 __________________________________ Number of solutions: 4 Number of backtracks: 0 Elapsed time: 00:00:00
pred _Ascending(x1::T, x2::T, x3::T, ..., xn::T) iff
x1 <= x2 & x1 <= x3 & ... x1 <= xn
For example, the following query
all x::[1..2] & y::[1..4] & z ::I[1..2] & _Ascending(x,y,z)will generate the following solutions:
x = 1 y = 1 z = 1 ___ Solution: 1 __________________________________ x = 1 y = 1 z = 2 ___ Solution: 2 __________________________________ x = 1 y = 2 z = 2 ___ Solution: 3 __________________________________ x = 2 y = 2 z = 2 ___ Solution: 4 __________________________________ Number of solutions: 4 Number of backtracks: 0 Elapsed time: 00:00:00
pred _AllDescending(x1::T, x2::T, x3::T, ..., xn::T) iff
x1 > x2 & x1 > x3 & ... x1 > xn
For example, the following query
all x::[1..3] & y::[1..3] & z ::I[1..3] & _AllDescending(x,y,z)will generate the following solutions:
x = 3 y = 2 z = 1 ___ Solution: 1 __________________________________ Number of solutions: 1 Number of backtracks: 0 Elapsed time: 00:00:00
pred _Descending(x1::T, x2::T, x3::T, ..., xn::T) iff
x1 >= x2 & x1 >= x3 & ... x1 >= xn
For example, the following query
all x::[1..2] & y::[1..2] & z ::I[1..2] & _Descending(x,y,z)will generate the following solutions:
x = 1 y = 1 z = 1 ___ Solution: 1 __________________________________ x = 2 y = 1 z = 1 ___ Solution: 2 __________________________________ x = 2 y = 2 z = 1 ___ Solution: 3 __________________________________ x = 2 y = 2 z = 2 ___ Solution: 4 __________________________________ Number of solutions: 4 Number of backtracks: 0 Elapsed time: 00:00:00