Utility Functions
LINGO offers a pair of utility functions for sorting attributes and sets, @RANK and @SORT:
@RANK( SET|ATTRIBUTE(S))
@SORT( SET|ATTRIBUTE(S))
These functions are used to either rank or sort the values of an attribute or the members of a set. @RANK returns a ranking vector, listing each member of the set or attributes position/rank once sorted into ascending order, while @SORT returns the ordering of the set members or attributes when sorted. Both functions are only available for use in calc sections.
As an example, consider the following small model:
model:
sets:
s1: x, rankx, sortx;
endsets
data:
x = 3.2 5.7 -1.1;
enddata
calc:
rankx = @rank( x);
sortx = @sort( x);
endcalc
end
The @RANK function will place the following values into the RANKX attribute: 2, 3, 1, indicating that X( 1) is the second from smallest value, X( 2) is the largest, and X( 3) is the smallest. @SORT, on the other hand, will return the indices of X in sorted order, i.e.: 3, 1, 2. You will note that these two functions are inverses of one another and that the following conditions hold:
RANK( SORT( i)) = i, and
SORT( RANK( i)) = i
In this next example, we generate a list of random numbers and then rank them with @RANK:
model:
! Generates 40,000 random numbers, ranks them
with @RANK(), and then moves them into sorted
order.;
sets:
s1 /1..40000/: xrand, xrank, xsort;
endsets
calc:
@set( 'terseo', 2);
seed = .5;
t0 = @time();
@for( s1( i):
xrand( i) = @rand( seed);
seed = xrand( i);
);
t1 = @time();
xrank = @rank( xrand);
t2 = @time();
@for( s1( i):
xsort( xrank( i)) = xrand( i);
);
t3 = @time();
@write(
' Time to generate: ', @format( t1 - t0, '8.2g'), @newline( 1),
' Time to rank: ', @format( t2 - t1, '8.2g'), @newline( 1),
' Time to move: ', @format( t3 - t2, '8.2g'), @newline( 2)
);
endcalc
end
Model: SORTRAND
The following code generates the random numbers through the use of the @RAND function:
@for( s1( i):
xrand( i) = @rand( seed);
seed = xrand( i);
);
Then, we rank the random values via @RANK with:
xrank = @rank( xrand);
The random values are then moved into sorted order using an @FOR loop:
@for( s1( i):
xsort( xrank( i)) = xrand( i);
);
Finally, we display the time these three operations used with the @WRITE statement:
@write(
' Time to generate: ', @format( t1 - t0, '8.2g'), @newline( 1),
' Time to rank: ', @format( t2 - t1, '8.2g'), @newline( 1),
' Time to move: ', @format( t3 - t2, '8.2g'), @newline( 2)
);
Running the model in LINGO will yield a report similar to the following:
Time to generate: 0.07
Time to rank: 0.01
Time to move: 0.05
Note: | Multiple attributes can be passed to both @RANK and @SORT to perform multidimensional sorts, e.g.: @SORT( X, Y, Z). Here, the sort would be performed first on X, with any ties in X being broken by Y, and so on. When specifying multiple attributes, all the attributes must be defined on the same set. |
Note: | Sets may also be sorted by passing the set name as the argument to both @RANK and @SORT, e.g.: @SORT( MY_SET_NAME). Only one set name may be specified when sorting sets. Combining set names and attributes in the same sort is not supported. Sorting a set can be useful to present written reports in sorted order. |
Note: | To rank or sort an object in descending order, precede the object with a minus sign, e.g., @RANK( -X) would rank X in descending order. |