Search code examples
recursionsassas-macro

Implementing recursive bisection in SAS


First question here.

Basically, I want to implement a recursive bisection algorithm in SAS via the use of macros. I have already written a macro that takes two arguments (the lower and upper endpoints of the current interval) and produces a table containing the two endpoints of another interval. The problem I'm having is writing a macro that will iterate this process until the width of the interval is below a certain threshold.

Here is what I have so far, but the code does not work as I expect. Bear in mind, 99% of everything I've ever learned about SAS, I learned in the past three days or so. Much thanks to anyone who can help!

data interval;
     input a b;
     datalines;
          0 1
          ;
run;

%macro iter(a,b);
data rec;
     set interval;
     %let a0 = &a;
     %let b0 = &b;
     %do %while(%sysevalf(&b0 - &a0) > .00001);
          %nextint(&a0,&b0);
          call symput('a0',trim(left(a)));
          call symput('b0',trim(left(b)));
     %end;
run;
%mend;

where %nextint(&a0,&b0) produces a table interval with one observation, and two columns a and b with the values calculated from &a0 and &b0. As you can see, SAS is a complete mystery to me and I don't know what I'm doing.


Solution

  • Not sure what your macro %nextint does, but I wrote something just to show how the %iter macro will run.

    You need to put those call symput's in a data step.

    I used null here just to get new values for the macro variables a0 and b0 from the interval data set.

    Note, this will produce the interval data set with the first set of values for a and b where b - a is less than 0.0001.

    The %put statements at the end of the macro will show you the changing values of a and b for each interation.

        %macro nextint(a1,b1);
            data interval;
                a = &a1. + 0.1;
                b = &b1. - 0.1;
            run;
        %mend;
    
    
        %macro iter(a,b);
            %let a0 = &a.;
            %let b0 = &b.;
            %do %while(%sysevalf(%sysevalf(&b0. - &a0.) > 0.0001));
                %nextint(&a0,&b0);
                data _null_;
                    set interval;
                    call symput('a0',strip(a));
                    call symput('b0',strip(b));
                run;
                %put &a0.;
                %put &b0.;
                %put %sysevalf(&b0. - &a0.);
            %end;
        %mend;
    
        %iter(0,1);