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 05-13-2011 08:36 AM
(2124 views)

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

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 "

Message was edited by: Rakesh Message was edited by: Rakesh

6 REPLIES 6

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

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?

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 "

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

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

...

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

...

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

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!

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!

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

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.

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.

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

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

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

/* 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]

f=.5*Proceeds;

else if NewPIPmt > ub | coeff[20]

f=.5*Proceeds;

else f=Proceeds;

return(f);

finish redefault;

Now, the non-linear constraint is that

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

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;

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;

**SAS Innovate 2025** is scheduled for May 6-9 in Orlando, FL. Sign up to be **first to learn** about the agenda and registration!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.