Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 01-27-2022 02:30 PM
(785 views)

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

Paige Miller

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

```
/*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!

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

In the outermost loop, i starts with 1, so i-1 resolves to zero, while the array starts at 1.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

**Available on demand!**

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

Upcoming Events

- PharmaSUG 2024 | 19-May-2024
- SAS Halifax Region User Group (SHRUG) Meeting | 23-May-2024
- What’s New in SAS Optimization? | 23-May-2024
- Montreal SAS User Group (MONSUG) Meeting | 29-May-2024
- Club des utilisateurs SAS de Québec | 30-May-2024
- Optimizing Logistics Operations Using Customized Solutions | 04-Jun-2024
- Toronto SAS Users' Community Luncheon | 04-Jun-2024

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.