This example illustrates how you can use the element constraint to represent almost any function between two variables in addition to representing nonstandard domains. Consider the following nonlinear optimization problem:
where is any integer in [–5, 5], is any odd integer in [–5, 9], and is any integer in [1, 10].
You can solve this problem by introducing four artificial variables, –, to represent each of the nonlinear terms. Let , , , and . You can represent the domains of and (which are not consecutive integers that start from 1) by using element constraints and index variables. For example, any of the following three element constraints specifies that the domain of is the set of odd integers in :
con element(z2,-5 -3 -1 1 3 5 7 9,x2); con element(z2, {ri in -5..9 by 2} ri, x2); num range{ri in -5..9 by 2} = ri; con element(z2,range,x2);
Any functional dependencies on or can now be defined using or , respectively, as the index variable in an element constraint. Because the domain of is , you can directly use as the index variable in an element constraint to define dependencies on .
For example, the following constraint specifies the function , :
con element(z1,-125 -64 -27 -8 -1 0 1 8 27 64 125,y1); /* or, con element(z1, {ri in -5..5} (ri**3), y1}; */ num range{ri in -5..5} = ri**3; con element(z1,range,y1);
To solve the problem, define the objective function as demonstrated in the following statements:
proc optmodel; set DOM{1..3} = [ (-5 .. 5) (-5 .. 9 by 2) (1 .. 10) ]; var X{i in 1..3} integer >= min{j in DOM[i]} j <= max{j in DOM[i]} j; /* map the domain of X[1] and X[2] to 1 .. list size */ var Z {1..2} integer; /* map nonlinear expressions */ var Y {1..4} integer; /* Use an element constraint to represent noncontiguous domains */ /* domains with negative numbers, and nonlinear functions. */ /* Z[2] does not appear anywhere else. Its only purpose is to restrict X[2] to take a value from DOM[2]. */ con MapDomainTo1ToCard{i in 1..2}: element(Z[i], {k in DOM[i]} k, X[i]); /* Functional Dependencies on X[1] */ /* Y[1] = X[1]^3 -- Use Z[1] for X[1] for proper indexing */ con Y1: element(Z[1], {k in DOM[1]} (k^3), Y[1]); /* Y[4] = mod(X[1], 4) */ con Y4: element(Z[1], {k in DOM[1]} (mod(k,4)), Y[4]); /* Functional Dependencies on X[3] */ /* Y[2] = 2^X[3] */ con Y2: element(X[3], {k in DOM[3]} (2^k), Y[2]); /* Y[3] = X[3]^2 */ con Y3: element(X[3], {k in DOM[3]} (k^2), Y[3]); /* X[1] - 0.5 * X[2] + X[3]^2 <= 50 */ con Con1: X[1] - 0.5 * X[2] + Y[3] <= 50; /* mod(X[1],4) + 0.25 * X[2] >= 1.5 */ con Con2: Y[4] + 0.25 * X[2] >= 1.5; /* Objective function: X[1]^3 + 5 * X[2] - 2^X[3] */ max Objective = Y[1] + 5 * X[2] - Y[2]; solve; print X Y Z; quit;
Output 6.4.1 shows the solution that corresponds to the optimal objective value of 168.
Output 6.4.1: Nonlinear Optimization Problem Solution
Problem Summary | |
---|---|
Objective Sense | Maximization |
Objective Function | Objective |
Objective Type | Linear |
Number of Variables | 9 |
Bounded Above | 0 |
Bounded Below | 0 |
Bounded Below and Above | 3 |
Free | 6 |
Fixed | 0 |
Binary | 0 |
Integer | 9 |
Number of Constraints | 8 |
Linear LE (<=) | 1 |
Linear EQ (=) | 0 |
Linear GE (>=) | 1 |
Linear Range | 0 |
Alldiff | 0 |
Element | 6 |
GCC | 0 |
Lexico (<=) | 0 |
Lexico (<) | 0 |
Pack | 0 |
Reify | 0 |
Constraint Coefficients | 5 |