Obsidian | Level 7

## taking the minimum of a matrix

Hi everybody, I will explain my problem :

I have a matrix with X and Y and the image of both by a funcion. Then I have 3 columns.

I want the minimum image of the function but keeping X and Y.

I have found the result but it is no so clean. I think that there is a better option. Look at the way I found it :

titi=min(pbest[,p+1]);

/*then we iterate to assign the coordinates of this minimum to gbest*/
do i=1 to n;
if pbest[i,p+1]=titi then gbest=pbest[i,];
else e=0;
end;

and this is another option I have tried :

titi=min(ncol(pbest[,p+1]));
print titi;

The idea is that I need what I have in the Row which has the minimum value in the column p+1

thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
SAS Super FREQ

## Re: taking the minimum of a matrix

In general, you can use the LOC function to find rows that satisfy some criterion.  The LOC function is the most important function that new SAS/IML programmers need to discover.  Be aware, however, if your matrix has tied values, you might get more than one row that satisfies the criterion. In that case, I assume any row is okay? If so, take the first:

proc iml;
pbest = {1 2 9,
4 5 6,
1 3 10,
4 1 3,
1 1 8,
5 2 3};
p = 2;
n = nrow(pbest);

titi=min(pbest[,p+1]);

/* 1. Use LOC to find row that satisfies criterion */
minIdx = loc(pbest[,p+1]=titi);
gbest = pbest[minIdx, ];     /* in case of tied values, might get more than one row */
print gbest;

gbest = pbest[minIdx[1], ];  /* if you only want one row, take first */
print gbest;

In this case, the "criterion" is actually a minimum. In SAS/IML, there is a special operator (the '>:<' subscript reduction operator) that can return the row for wh...

/* 2. For the MIN, you can also use v[>:,] to get the index directly */
v = pbest[,p+1];
minIdx = v[>:<];
print minIdx;
gbest = pbest[minIdx, ];     /* always returns one row */
print gbest;

3 REPLIES 3
Diamond | Level 26

## Re: taking the minimum of a matrix

You can find the minimum of a column (or minimum of a matrix, or minimum of a row) by using subscript reduction operators. https://documentation.sas.com/doc/en/imlug/15.2/imlug_workmatrix_sect025.htm

It's really hard to visualize what the matrix is that you have and what matrix you want by reading your description in words. Also, at one point you say "minimum of a matrix" and at other times you appear to want the minimum of a column. It would help greatly if you could provide a small example.  Show us what you have and what you want.

--
Paige Miller
Obsidian | Level 7

## Re: taking the minimum of a matrix

Thank you for your answer. In fact, I can show you my code. And I will try to explain it better, sorry.

I have a matrix with 3 columns and 20 lines. The first column is the value for X, the second one for Y and the third one is f(X,Y), the image of x and y by a function f. I want the minimum of the function, then it is the minimum of the third column. This is easy, it is min(X[,p+1]). With p the number of variables (2) and all the lines. And I have the result which is the minimum. BUT I don't have the values for the other columns for this minimum. I would like to have the entire row where the value of the image is minimum.

Here the code. In this case we are talking about gbest and pbest.

proc iml;
xmin=0;     /* min has to be >= 0 or else x^(1/4) and x^(3/4) are undefined */
xmax=100;
/***parameters and variables***/
n=20;			   			/*number of particles*/
p=2;
maxt=1000;					/*maximum iteration*/
maxrun=1;					/*trials of the algorithm*/
X=j(n,p+1,0);				/*initialization of the particle's matrix*/
lb=j(1,p,xmin);
ub=j(1,p,xmax);

/* vectorization of f: R^2 --> R */
start f(x);
con=100*x[,1]+200*x[,2]-1500;
fc = 3*(x[,1]##0.25) # (x[,2]##0.75);
pen=10**9;
idx = loc(con > 0);
if ncol(type)>0 then
fc[idx] = pen*con[idx];
return(fc);
finish f;

call randseed(1234);
Y = j(n,P);/* allocate for random values */
do run=1 to maxrun; /*this line is not important in this example*/
/***initialization of the pso***/
call randgen(Y, 'uniform');

/*sample in a uniform distribution to initialize the particles position*/
X[,1:p] = lb + (ub-lb)#Y;
/*to fill the third column of X (which corresponds to the output of the function), we evaluate the fitting for each particule*/
X[,p+1]= f(X);

pbest=X;			/*initialization of pbest so we can iterate then*/
V=0.1*X;
/*we find the current minimum of f, given the current values of X (if we want to minimize the function)*/
titi=min(pbest[,p+1]);
/*then we iterate to assign the coordinates of this minimum to gbest*/
do i=1 to n;
if pbest[i,p+1]=titi then gbest=pbest[i,];
else e=0;
end;
end;
print gbest;

I would like to take away the titi and all this stuff.

SAS Super FREQ

## Re: taking the minimum of a matrix

In general, you can use the LOC function to find rows that satisfy some criterion.  The LOC function is the most important function that new SAS/IML programmers need to discover.  Be aware, however, if your matrix has tied values, you might get more than one row that satisfies the criterion. In that case, I assume any row is okay? If so, take the first:

proc iml;
pbest = {1 2 9,
4 5 6,
1 3 10,
4 1 3,
1 1 8,
5 2 3};
p = 2;
n = nrow(pbest);

titi=min(pbest[,p+1]);

/* 1. Use LOC to find row that satisfies criterion */
minIdx = loc(pbest[,p+1]=titi);
gbest = pbest[minIdx, ];     /* in case of tied values, might get more than one row */
print gbest;

gbest = pbest[minIdx[1], ];  /* if you only want one row, take first */
print gbest;

In this case, the "criterion" is actually a minimum. In SAS/IML, there is a special operator (the '>:<' subscript reduction operator) that can return the row for wh...

/* 2. For the MIN, you can also use v[>:,] to get the index directly */
v = pbest[,p+1];
minIdx = v[>:<];
print minIdx;
gbest = pbest[minIdx, ];     /* always returns one row */
print gbest;

From The DO Loop