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 fist 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.