Calcite | Level 5

## Call NLPQN inside PROC IML

How can I inform SAS that my decision variable is K inside the following nonlinear programming model ? what is missing in this code in order to give me optimal value of K? where lambda, g, estvar, col11,col2,col3 are stored vectors

Proc iml;
start fun(K);
sumf=0;
do i = 1 to 3;
sumf = sumf + (estvar*lambda)+ (g* k)**2 /(lambda+ k)**2;
end;
return (sumf);
finish fun;
start con(k);
c=j(4,1,0);
sumc1=0;
do i = 1 to 3;
sumc1 = sumc1 + (col1**2 *lambda/(lambda+k)**2);
end;
c[1]= 10-sumc1;
sumc2=0;
do i= 1 to 3;
sumc2 = sumc2 + (col2**2 *lambda/(lambda+k)**2);
end;
c[2]= 10-sumc2;
sumc3=0;
do i= 1 to 3;
sumc3 = sumc3 + (col3**2 *lambda/(lambda+k)**2);
end;
c[3]= 10-sumc3;
c[4]=(max(lambda)/min(lambda))-(max(lambda)+k)/(min(lambda)+k);
return (c);
finish con;
optn=j(1,11,.); optn[4]=1; optn[6]=2; optn[11]=0; optn[10]=4;
call nlpqn (rc, kres, "fun", k, optn) nlc="con";
11 REPLIES 11
SAS Employee

## Re: Call NLPQN inside PROC IML

IML knows that k is the decision variable, from your specification of the objective function module fun(K). However, in the nlpqr call you need to give it an initial starting point for the optimization, in the 4th parameter, i.e.:

k0 = 1;
call nlpqn (rc, kres, "fun", k0, optn) nlc="con";

If your initial point is infeasible, IML will find one for you. Also, you need to pass in the values of your global parameters to your objective and constraint modules, via a global() clause in the START statement, i. e. :

start fun(K)global(lambda, estvar, g);

start con(k)global(lambda, col1, col2, col3);

Of course you will also need statements to set the values of lambda, estvar, g, col1, col2, and col3 before you call nlpqn.
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

what is the optimal k value? is it kres in my code?
SAS Employee

## Re: Call NLPQN inside PROC IML

Yes. Also, if you set the print option to 2 (optn[2] = 2) you will get an informative printout of the iteration history and constraint satisfaction.
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

Is there any option to increase the decimal places of k optimal inside call statement?
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

Another question, I want c[1], c[2], c[3], and c[4] which are my 4 constraints to be greater than or equal zero, is this correct in my code?
SAS Employee

## Re: Call NLPQN inside PROC IML

to : "Another question, I want c[1], c[2], c[3], and c[4] which are my 4 constraints to be greater than or equal zero, is this correct in my code?"

Your code appears to be correct.
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

I want my code using proc iml (code1) to be the same as the one using proc optmodel (code2), Is they are the same ? as they give me different results for K. If they are not the same, What is missing in code 1 to be the same as code 2? moreover, in code 2 we can tell SAS that K is positive (var k >=0;) so, I want to put K as positive variable in code 1 as well, How can I do so?

code1:

Proc iml;
start fun(K);
sumf=0;
do i = 1 to 3;
sumf = sumf + (estvar*lambda)+ (g* k)**2 /(lambda+ k)**2;
end;
return (sumf);
finish fun;
start con(k);
c=j(4,1,0);
sumc1=0;
do i = 1 to 3;
sumc1 = sumc1 + (col1**2 *lambda/(lambda+k)**2);
end;
c[1]= 10-sumc1;
sumc2=0;
do i= 1 to 3;
sumc2 = sumc2 + (col2**2 *lambda/(lambda+k)**2);
end;
c[2]= 10-sumc2;
sumc3=0;
do i= 1 to 3;
sumc3 = sumc3 + (col3**2 *lambda/(lambda+k)**2);
end;
c[3]= 10-sumc3;
c[4]=(max(lambda)/min(lambda))-(max(lambda)+k)/(min(lambda)+k);
return (c);
finish con;
optn=j(1,11,.); optn[4]=1; optn[6]=2; optn[11]=0; optn[10]=4;
call nlpqn (rc, kres, "fun", k, optn) nlc="con";

code2:

proc optmodel;
var k >=0;
set ISET;
num lambda {ISET};
num g {ISET};
num col1 {ISET};
num col2 {ISET};
num col3 {ISET};
num min_lamb = min {i in ISET} lambda;
num max_lamb = max {i in ISET} lambda;
read data sasdata.sxlamb2 into ISET = [_n_] lambda g;
read data work.datavif into ISET = [_n_] col1 col2 col3;
num estvar ;
min f = sum {i in ISET}((estvar*lambda)+(k**2 *g **2)/(lambda+k)**2);
con co1: sum {i in ISET}(col1**2 *lambda/(lambda+k)**2)<=10;
con co2: sum {i in ISET}(col2**2 *lambda/(lambda+k)**2)<=10;
con co3: sum {i in ISET}(col3**2 *lambda/(lambda+k)**2)<=10;
con co4: (max_lamb+k)/(min_lamb+k)<= max_lamb/min_lamb;
solve with nlpc / tech =qne;
print k ;
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

I want my code using proc iml (code1) to be the same as the one using proc optmodel (code2), Is they are the same ? as they give me different results for K. If they are not the same, What is missing in code 1 to be the same as code 2? moreover, in code 2 we can tell SAS that K is positive (var k >=0;) so, I want to put K as positive variable in code 1 as well, How can I do so?

code1:

Proc iml;
start fun(K);
sumf=0;
do i = 1 to 3;
sumf = sumf + (estvar*lambda)+ (g* k)**2 /(lambda+ k)**2;
end;
return (sumf);
finish fun;
start con(k);
c=j(4,1,0);
sumc1=0;
do i = 1 to 3;
sumc1 = sumc1 + (col1**2 *lambda/(lambda+k)**2);
end;
c[1]= 10-sumc1;
sumc2=0;
do i= 1 to 3;
sumc2 = sumc2 + (col2**2 *lambda/(lambda+k)**2);
end;
c[2]= 10-sumc2;
sumc3=0;
do i= 1 to 3;
sumc3 = sumc3 + (col3**2 *lambda/(lambda+k)**2);
end;
c[3]= 10-sumc3;
c[4]=(max(lambda)/min(lambda))-(max(lambda)+k)/(min(lambda)+k);
return (c);
finish con;
optn=j(1,11,.); optn[4]=1; optn[6]=2; optn[11]=0; optn[10]=4;
call nlpqn (rc, kres, "fun", k, optn) nlc="con";

code2:

proc optmodel;
var k >=0;
set ISET;
num lambda {ISET};
num g {ISET};
num col1 {ISET};
num col2 {ISET};
num col3 {ISET};
num min_lamb = min {i in ISET} lambda;
num max_lamb = max {i in ISET} lambda;
read data sasdata.sxlamb2 into ISET = [_n_] lambda g;
read data work.datavif into ISET = [_n_] col1 col2 col3;
num estvar ;
min f = sum {i in ISET}((estvar*lambda)+(k**2 *g **2)/(lambda+k)**2);
con co1: sum {i in ISET}(col1**2 *lambda/(lambda+k)**2)<=10;
con co2: sum {i in ISET}(col2**2 *lambda/(lambda+k)**2)<=10;
con co3: sum {i in ISET}(col3**2 *lambda/(lambda+k)**2)<=10;
con co4: (max_lamb+k)/(min_lamb+k)<= max_lamb/min_lamb;
solve with nlpc / tech =qne;
print k ;
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

the rest of code 2:

con co1: sum {i in ISET}(col1**2 *lambda/(lambda+k)**2)<=10;
con co2: sum {i in ISET}(col2**2 *lambda/(lambda+k)**2)<=10;
con co3: sum {i in ISET}(col3**2 *lambda/(lambda+k)**2)<=10;
con co4: (max_lamb+k)/(min_lamb+k)<= max_lamb/min_lamb;
solve with nlpc / tech =qne;
print k ;
Calcite | Level 5

## Re: Call NLPQN inside PROC IML

the rest of code2:

con c1: sum {i in ISET}(col1**2 *lambda/(lambda+k)**2)<=10;
con c2: sum {i in ISET}(col2**2 *lambda/(lambda+k)**2)<=10; con c3: sum {i in ISET}(col3**2 *lambda/(lambda+k)**2)<=10; con c4: (max_lamb+k)/(min_lamb+k)<= max_lamb/min_lamb;
solve with nlpc / tech =qne;
print k ;
SAS Employee

## Re: Call NLPQN inside PROC IML

The algorithm used by NLPQN does not by design generate a sequence of closer and closer approximations to the x value, and therefore you can't use the difference in x between iterations as a convergence criteria. However, if you use NLPNMS (Nelder-Meade-Simplex), you can specify a value for for termination criteria tc[9] (ABSXCONV) that will terminate the optimization when x is changes by less than that amount, i.e.:

t = j(10,1,.);
t[9] = 1e-9;
call nlpnms (rc, kres, "fun", k0, optn) nlc="con" tc = t;

If you change your optn[2] value to 3, you will get a detailed printout of the x and objective value at each iteration of the optimization process. Look at the IML doc under "Nonlinear Optimization Examples"-> "Details"->"Termination Criteria" for a full explanation of the termination criteria available with NLPNMS
From The DO Loop