The Constraint Programming Solver
ELEMENT Predicate
ELEMENT(scalar-variable,data-list,scalar-variable)
The ELEMENT predicate specifies an array element lookup constraint, which enables you to define dependencies (which are not necessarily functional) between variables.
The predicate ELEMENT sets the variable V to be equal to the Ith element in the list L, where is a list of values (not necessarily distinct) that the variable V can take. The variable I is the index variable, and its domain is considered to be . Each time the domain of I is modified, the domain of V is updated, and vice versa.
For example, the following statements use the ELEMENT predicate to determine whether there are squares greater than 1 that are also elements of the Fibonacci sequence:
/* Are there any squares > 1 in the Fibonacci sequence? */
proc optmodel;
num n = 20;
/* 1 appears twice in the Fibonacci sequence */
num fib{i in 1..n} = if i < 3 then 1 else fib[i-1] + fib[i-2];
var IFib integer, ISq integer,
XFib integer, XSq integer;
con IsFibAndIsSquare: XFib = XSq;
/* You can use a numeric array to refer to a list */
con IdxOfFib: element( IFib, fib, XFib );
/* You can also build a list from a set iterator */
con IdxOfSq: element( ISq, {i in 2..n} (i * i), XSq );
solve;
print XFib XSq;
quit;
An element constraint enforces the propagation rules
where v is a value in the list L and are all the indices in L whose value is v.
An element constraint is equivalent to a conjunction of reify and linear constraints. For example, both of the following examples implement the quadratic function, :
Using the ELEMENT predicate:
proc optmodel; var X >= 1 <= 5 integer, Y >= 1 <= 25 integer; num a {i in 1..5} = i^2; con Mycon: element(X, a, Y); solve; quit;Using linear constraints and the REIFY predicate:
proc optmodel; var X >= 1 <= 5 integer, Y >= 1 <= 25 integer, R {1..5} binary; con MyconX {i in 1..5}: reify(R[i], X = i); con MyconY {i in 1..5}: reify(R[i], Y = i^2); con SumToOne: sum {i in 1..5} R[i] = 1; solve; quit;
You can also use element constraints to define positional mappings between two variables. For example, suppose the function is defined on only odd numbers in the interval . You can relate X and Y by using two element constraints and an artificial index variable:
var I integer, X integer, Y integer; /* You can also build a list by providing explicit literals. */ con XsubI: element (I, -5 -3 -1 1 3 5, X); con YsubI: element (I, 25 9 1 1 9 25, Y);