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
(750 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

**Don't miss out on SAS Innovate - Register now for the FREE Livestream!**

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

Upcoming Events

- SAS Innovate | 16-Apr-2024
- From Zero to SAS: Using SAS Tasks to Summarize and Manipulate Your Data | 25-Apr-2024
- Free Webinar from Michigan SAS User Group | 25-Apr-2024
- How Can You Use Deep Learning for Personalized Pricing and Revenue Optimization? | 02-May-2024
- SAS® Enterprise Guide® Is Now Integrated With SAS® Viya® 4 | 07-May-2024
- Iowa SAS Users Group: The 14th One-Day Conference | 13-May-2024
- Nebraska SAS Users Group (NEBSUG) One-Day SAS Conference | 14-May-2024

5 Steps to Your First Analytics Project Using SAS

For SAS newbies, this video is a great way to get started. James Harroun walks through the process using SAS Studio for SAS OnDemand for Academics, but the same steps apply to any analytics project.

Find more tutorials on the SAS Users YouTube channel.