Statistical programming, matrix languages, and more

Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

Reply
Occasional Contributor
Posts: 5

Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

I have been trying to setup a nonlinear constraint for a genetic algorithm in SAS 9.2 for some time now.
The constraint is as follows;

(-0.3) <= mort(x[1],.,x[2]/12,x[3]) / mort(coeff[1],.,coeff[2]/12,coeff[3]) <= -0.1
Now, the nonlinear optimization calls like "nlpqn" let me specify nonlinear constraints with the "nlc" module. Do we have something similar for genetic algorithms?

Message was edited by: Rakesh Message was edited by: Rakesh
Occasional Contributor
Posts: 5

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

My earlier post didn't print properly on the thread. This is what I was trying to say;

I have been trying to setup a nonlinear constraint for a genetic algorithm in SAS 9.2 for some time now.
The constraint is as follows;

(-0.3) LT mort(x[1],.,x[2]/12,x[3]) / mort(coeff[1],.,coeff[2]/12,coeff[3]) LT -0.1

where, LT stands for "Less than or Equal To"

Now, the nonlinear optimization calls like "nlpqn" let me specify nonlinear constraints with the "nlc" module. Do we have something similar for genetic algorithms?
SAS Employee
Posts: 94

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

In general, with GA there are several different strategies for satisfying non-linear constraints. Probably the simplest way within IML for this particular problem is to simply "fix up" any solution that does not satisfy the non-linear constraint so that it does match the constraint. In this case, by the nature of the mort() function, the constraint violation function is linear in the first component x[1] ( the initial mortgage amount). That makes it easy to adjust your solution to reside on the nearest constraint boundary by modifying x[1] and leaving the other components unchanged. You can do that in the objective function with something like:

start objective(x) global( coeff );
/* assumes desired soution vector is in x, coeff is constant matrix */

/* First, get the lower (lb) and upper (ub) bounds of the quantity
mort(x[1],.,x[2]/12,x[3])
*/

const = mort(coeff[1],.,coeff[2]/12,coeff[3]); /* denominator */

if const > 0 then do;
ub = -0.1 * const;
lb = -0.3 *const;
end;

else do;
ub = -0.3 * const;
lb = -0.1 * const;
end;

/* Now, fix up x[1] to make sure the constraint is satisfied */

x0 = x[1];
payment = mort(x0,.,x[2]/12,x[3]);

if lb > payment then
x[1] = x0 * lb / payment;

else if payment > ub then
x[1] = x0 * ub / payment;

/* now you have "fixed up" your solution to satisfy the constraint, go ahead and
compute the objective function */

...
Occasional Contributor
Posts: 5

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

Thanks a lot Hutch. The answer was helpful.

The problem I have is that I need to be able to vary all three parts of the mort() function to achieve this. So, whereas the function is linear in initial balance , it is not in the Interest Rate (x[2]) and the Amortization Term (x[3]). How do I change all three together, how do I distribute the bounds as weighting parameters amongst the three 'variables'?

Do let me know if you have a solution. Your earlier answer did open a few door for me!
SAS Employee
Posts: 94

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

Using this strategy you can still vary all three parameters. I assume you can assign reasonable upper and lower bounds for each variable, and then generate a uniform distribution of solutions across those bounds. This fixup strategy then maps in a certian way the solutions that fall outside the constraint to the constraint boundary.

What is your actual objective function for this problem? Depending on your objective, you might also be able to transform variables to produce easier constraints.
Occasional Contributor
Posts: 5

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

Thanks Hutch.

Below is the code for the objective function i'm trying to maximize;

proc iml;

/* objective function, has minimum of 0 at x = xopt */
start redefault(x) global(coeff);

NewUPB=(1+coeff[14]-x[3]-x[4])*coeff[19];
NewPIPmt=mort((1+coeff[14]-x[3]-x[4])*coeff[19],.,x[1]/12,x[2]-coeff[22]);
OldPIPmt=mort(coeff[19],.,coeff[20]/12,coeff[21]-coeff[22]);
CurrLTV=(1+coeff[14]-x[3]-x[4])*coeff[19]/coeff[18];
LTVBasedOnOrigMV=(1+coeff[14]-x[3]-x[4])*coeff[19]/coeff[17];

/*Upper and Lower Bounds for Chng in Pmt*/
if OldPIPmt > 0 then do;
ub = (1-0.1) * OldPIPmt;
lb = (1-0.3) * OldPIPmt;
end;

else do;
ub = (1-0.3) * OldPIPmt;
lb = (1-0.1) * OldPIPmt;
end;

/*Fixup Variables - NOT BEING USED CURRENTLY*//*
do while (lb>NewPIPmt);
x[1]=x[1]+.000125;
x[2]=x[2]-12;
/*x[3]=x[3]+.005;
x[4]=x[4]+.005;
NewPIPmt=mort((1+coeff[14]-x[3]-x[4])*coeff[19],.,x[1]/12,x[2]-coeff[22]);
end;

do while (NewPIPmt > ub);
x[1]=x[1]-.000125;
NewPIPmt=mort((1+coeff[14]-x[3]-x[4])*coeff[19],.,x[1]/12,x[2]-coeff[22]);
end;
*/


RedefRt=1/(1+exp(-1*
(-5.2815+
1.8953*(NewPIPmt/OldPIPmt-1)+
1.6129*log(1+coeff[2])+
0.1531*coeff[3]+
0.3222*CurrLTV+
0.4368*LTVBasedOnOrigMV+
-2.7613*(coeff[4]- 1) +
0.00531*coeff[5]+
-0.6964*coeff[6]+
-0.2283*coeff[7]+
0.7078*coeff[8]+
0.1932*coeff[9]+
1.2001*coeff[10]+
0.3751*coeff[11]+
0.000808*coeff[12]+
-0.00297*coeff[13]+
0.9974*coeff[14]+
0.1633*coeff[15]+
-0.0949*coeff[16])));

Proceeds = ((mort(.,NewPIPmt,x[1]/12,x[2]-coeff[22]-coeff[2])+(x[3]*coeff[19]))*(1-RedefRt) + coeff[23]*RedefRt);

/* Penalize the children that don't conform to the constraints */
if lb > NewPIPmt | coeff[20] x[2] then
f=.5*Proceeds;
else if NewPIPmt > ub | coeff[20] x[2] then
f=.5*Proceeds;
else f=Proceeds;

return(f);
finish redefault;


Now, the non-linear constraint is that (NewPIPmt/OldPIPmt-1) should be between -0.3 and -0.1, by varying the x[] parts of NewPIPmt.
SAS Employee
Posts: 94

Re: Specifying nonlinear constraints for a genetic algorithm in SAS 9.2

I don't have complete knowledge of your model, but could you use the ratio:

NewPIPmt/OldPIPmt

as one of your input parameters, instead of what you now have as x[4]? Since your x[4] only appears in the computation of of NewUPB, which would be computed directly from the mort() function, it would then go away and you could use x[4] for the new payment ratio parameter. Mathematically you could then just specify the correct bounds on that ratio directly and eliminate the non-linear constraint. Your objective might look something like this:


/* objective function, has minimum of 0 at x = xopt */
start redefault(x) global(coeff);
OldPIPmt=mort(coeff[19],.,coeff[20]/12,coeff[21]-coeff[22]);
/* let x[4] = NewPIPmt/OldPIPmt */
NewPIPmt = x[4] * OldPIPmt;
/* solve for new principal */
NewUPB = mort( ., NewPIPmt, x[1]/12,x[2]-coeff[22]);
CurrLTV = NewUPB/coeff[18];
LTVBasedOnOrigMV = NewUPB/coeff[17];

RedefRt=1/(1+exp(-1*
(-5.2815+
1.8953*(NewPIPmt/OldPIPmt-1)+
1.6129*log(1+coeff[2])+
0.1531*coeff[3]+
0.3222*CurrLTV+
0.4368*LTVBasedOnOrigMV+
-2.7613*(coeff[4]- 1) +
0.00531*coeff[5]+
-0.6964*coeff[6]+
-0.2283*coeff[7]+
0.7078*coeff[8]+
0.1932*coeff[9]+
1.2001*coeff[10]+
0.3751*coeff[11]+
0.000808*coeff[12]+
-0.00297*coeff[13]+
0.9974*coeff[14]+
0.1633*coeff[15]+
-0.0949*coeff[16])));

Proceeds = ((mort(.,NewPIPmt,x[1]/12,x[2]-coeff[22]-coeff[2])+(x[3]*coeff[19]))*(1-RedefRt) + coeff[23]*RedefRt);

return(Proceeds);
finish;
Ask a Question
Discussion stats
  • 6 replies
  • 585 views
  • 0 likes
  • 2 in conversation