BookmarkSubscribeRSS Feed
sarrabeny
Fluorite | Level 6

Hello everyone,

 

I would need your help about a do until loop. Here's my code : 

 

if t=&t then stop;
do i = 1 to &p;
do z=1 to &g;
do j = 1 to &nbx;
do until ( x[j,i]-x[j,i-1] = 1e-7);

........

The aim of this loop is to calculate the difference between the array x[j,i] and the one of the previous iteration (I am not sure if this the right syntax for that : x[j,i-1]), and then to stop the loop when this difference is close to 0. 

I also have another criteria : if the "do until criteria" isn't satisfied, then stop the loop when t=&t.

 

I have this error message :  Array subscript out of range at line 7459 column 35. (line 7459 is do until ( x[j,i]-x[j,i-1] = 1e-7);)

 

 

Thank you for your help!

 

 

8 REPLIES 8
PaigeMiller
Diamond | Level 26

Can we see the whole PROC code or the whole DATA step code, instead of this small portion? What is &t? Where does it get assigned and changed? What are the other macro variables? Are they ever zero or negative or missing? Are they are ever non-integers?

 

Please post your code in a code text box, which is the little running man icon. Thanks.

--
Paige Miller
sarrabeny
Fluorite | Level 6
if t=&t then stop;
 	do i = 1 to &p;
		do z=1 to &g;
 			do j = 1 to &nbx;
				do until ( x[j,i]-x[j,i-1] = 1e-7);	
				

 /* Compute new velocity and restrict it within minima and maxima */
 				v[j,i] = &chi*(&w*v[j,i] + &c1 * &r1 * (pbest[j,i] - x[j,i]) + &c2 * &r2 * (gbest[j] - x[j,i]));
 				v[j,i] = min(&vmax, max(-&vmax, v[j,i]));
 /* Move particle to new position and restrict them to the UP and LB  */
 				x[j,i] = x[j,i]+ v[j,i];
				x[j,i] = min(&UB, max(&LB, x[j,i]));

Here is a bigger part of the code, &t is a variable that I initialize in the first part with &let t=1000 for example. It's the iterations, the number of time I want my code to run.

 

 

Kurt_Bremser
Super User

We need to see the whole DATA step code, and we need to know the values of all macro variables used in the code. The log (which is equally important) will reveal the values of all variables at the moment of the crash.

sarrabeny
Fluorite | Level 6
/*Before running this script, you should run the script "Test functions" to initialize the functions we'll be
working on*/

/*-------------------------------------------------------PSO code----------------------------------------------------*/

/*  PSO parameters */
%let nbx = 2; /* Number of variables */
%let p = 20; /* Number of particles */
%let g = 19 ;/* Number of relations between particles : we take p-1 for the global topology */
%let t = 1000; /* Number of iterations */
%let UB = 5; /* Upper bound on solution */
%let LB = -5; /* Lower bound on solution */
%let vmax =(&UB-&LB)/2; /* Maximum velocity */
%let c1 = 2.05; /* Weight on pull toward best particle position */
%let c2 = 2.05; /* Weight on pull toward best global position */
%let func=rosenbrock; /*The function to minimize*/
%let r1=uniform(0); /* Random variable */
%let r2=uniform(0); /* Random variable */
%let c = &c1 + &c2;/* Acceleration coefficient */
%let chi =2/((&c-2)+sqrt(&c**2-4*&c)); /* Constriction coefficient */
%let w=0.5*uniform(0)+0.5; /* Inertia weight */


/* PSO code */

data solution_canonical;

 /* Define arrays for particle position(=x), velocity(=v), bests(pbest and gbest)
and one to store the pbests of the objective function */
 array x[&nbx,&p];
 array v[&nbx,&p];
 array pbest[&nbx,&p];
 array gbest[&nbx];
 array fpbest[&p];
 array n[&nbx,&g];
 array nbest[&nbx,&g];
 array fnbest[&g];
 

 /* Initialize arrays with random particle locations and velocities */
 do i = 1 to &p;
 	do z = 1 to &g;
 		do j = 1 to &nbx;
 			x[j,i] = &LB + (&UB - &LB)*&r1; /* Random particles locations */
			n[j,z] = &LB + (&UB - &LB)*&r1; /* Random neighbors locations */
 			v[j,i] = -&vmax +(2*&vmax)*&r1; /* Random particles velocities */
 			pbest[j,i] = x[j,i];
			nbest[j,z]= n[j,z];
			fpbest[i] = %f(%str(pbest[:,i]), func=&func);
			fnbest[z]= %f(%str(nbest[:,z]), func=&func);
 		end;
 		if i = 1 and z = 1 then do; 
			do j = 1 to &nbx;
      			gbest[j] = x[j,i];
 			end;

 /* Store the value of the objective function at the global best */
			fgnbest = fnbest[z];
			fgbest = fpbest[i];
 			end;
 		else do;
 			if fnbest[z] < fgnbest then do;
 				do j = 1 to &nbx;
 					gbest[j] = n[j,z];
 				end;
			
			if fpbest[i] < fnbest[z] then do;
  				do j = 1 to &nbx;
  					gbest[j] = x[j,i];
				end;
			if fpbest[i] < fgbest then do;
  				do j = 1 to &nbx;
  				gbest[j] = x[j,i];
			end;
				end;
 			fgbest = fpbest[i];
 			end;
			
 		end;
 	end;
end;

 /* Here is the fun part : Update particle locations and velocities to let them wander*/
 /* For each iteration, particle and variable */
if t=&t then stop;
 	do i = 1 to &p;
		do z=1 to &g;
 			do j = 1 to &nbx;
				do until ( x[j,i]-x[j,i-1] = 1e-7);	
				

 /* Compute new velocity and restrict it within minima and maxima */
 				v[j,i] = &chi*(&w*v[j,i] + &c1 * &r1 * (pbest[j,i] - x[j,i]) + &c2 * &r2 * (gbest[j] - x[j,i]));
 				v[j,i] = min(&vmax, max(-&vmax, v[j,i]));
 /* Move particle to new position and restrict them to the UP and LB  */
 				x[j,i] = x[j,i]+ v[j,i];
				x[j,i] = min(&UB, max(&LB, x[j,i]));
	
			end;
			end;
			
			

 /* Calculate the best particle in each neighborhood and THEN update particle and global best positions (if new best found) */

fx= %f(%str(x[:,i]), func=&func);
			if fx < fnbest[z] then do;
				do j = 1 to &nbx;
					nbest[j,z] = n[j,z];
  					fpbest[i] = fnbest[z];
				end;
			if fx < fpbest[i] then do;
 				do j = 1 to &nbx;
 					pbest[j,i] = x[j,i];
 					fpbest[i] = fx;
				end;
 			if fx < fgbest then do;
 				do j = 1 to &nbx;
 					gbest[j] = x[j,i];
 				end;
			fgbest = fx;

end;
end;
*end;
end;
end;



end;
end;



/* Record the iterations and global best position as the output solution */
/*do j = 1 to &nbx;
	do i = 1 to &p;
 		var_iteration_indice = "x"  || strip(i) || strip(j) ;
 		iteration_solution = pbest[j,i];
 	output;
 	end;
end;
keep  var_iteration_indice  iteration_solution;*/

do j = 1 to &nbx;
	var_indice = "x"  || strip(j) ;
	global_solution = gbest[j];
output solution_canonical;
end;
keep var_indice  global_solution  ;

run;




proc transpose data=Solution_canonical  out=newt;
var global_solution;
run;

data newt;
set newt;
rename COL1=x1 col2=x2;
run;

data params(type=est);
set newt;
_TYPE_='PARMS';
run;

proc nlp tech=NEWRAP  gradcheck=detail gconv2=1e-21 inest=params;
min f;
parms x1, x2;
f = rosenbrock(x1,x2);
run;

Here's the whole code!

ballardw
Super User
				do until ( x[j,i]-x[j,i-1] = 1e-7);	

Whenever the outer loop of i=1 to whatever executes and i=1f then you have 

x[j,i-1] referencing x[j,0]

so if x isn't defined in a way to allow an index of 0 in that second position then "i-1" is out of range.

 

 

Save yourself some work and copy an entire proc or data step section from the log with the error message and paste into a text box opened on the forum with the </> icon.

Sometimes the actual cause of your error can be quite separate from the statement(s) that SAS is reporting the error for. So the entire step is usually needed.

 

 

sarrabeny
Fluorite | Level 6

Thank you for your response! How can I correct this do you think? I tried to replace my i=1 to i=2 in all the code but it doesn't seem to work..

FreelanceReinh
Jade | Level 19

Hello @sarrabeny,


@sarrabeny wrote:


do until ( x[j,i]-x[j,i-1] = 1e-7);

........

The aim ... is ... to stop the loop when this difference is close to 0. 

Apart from the issue with the array subscripts: Shouldn't the check for the difference being "close to 0" rather use "... < 1e-7" or "... <= 1e-7" than exact equality? And also possibly an absolute value: 0 <= abs(...-...) < 1e-7, unless negative differences can be ruled out? Even if exact equality was the intended criterion, it would often fail due to numeric representation errors.

 

Example (log from Windows SAS 9.4M5):

124   data _null_;
125   x=0.1234561;
126   y=0.123456;
127   if round(x-y,1e-10)=1e-7 then put 'equal';
128   if x-y=1e-7 then put 'exactly equal';
129   d=x-y-1e-7;
130   put d=;
131   run;

equal
d=2.875571E-18

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 8 replies
  • 1379 views
  • 5 likes
  • 5 in conversation