Dear Sir or Madam,
I’m using PROC GA as a candidate tool for a model optimization task, going through the procedure documentation I wasn’t able to find any reference for optimization convergence graphs. Is there a way to output the best solution for each optimization step so that I can generate the graph myself?
Thanks in advance.
Best Regards,
Davi Laraia
Hi Davi,
PROC GA provides a hook for an update routine, called each iteration. You can use this to do things like report the iteration count and current best objective. Below is an example the prints the best objective each iteration to Output.
Best,
--Josh
OPTIONS NODATE NONUMBER;
TITLE "Iteration history";
TITLE "Iteration history output";
proc ga seed = 555;
call SetEncoding('R3R2');
npoints = 3;
array cvxhull[3,2] /nosym ( -2 0
0 2
2 -2 );
/* Objective function */
function sixhump(selected[*],cvxhull[*,*],npoints);
/* Function has global minimum value of -1.0316
* at x = {-0.0898 0.7126} and
* x = { 0.0898 -0.7126}
*/
array w[1] /nosym;
call dynamic_array(w,npoints);
array x[2] /nosym;
call ReadMember(selected,1,w);
/* make sure that weights add up to 1 */
sum = 0;
do i = 1 to npoints;
sum + w[i];
end;
/* if all weights 0, then reinitialize */
if sum=0 then do;
sum = npoints;
do i = 1 to npoints;
w[i] = 1;
end;
end;
/* re-normalize weights */
do i = 1 to npoints;
w[i] = w[i] / sum;
end;
call WriteMember(selected,1,w);
/* convert weights to x-coordinate form */
x[1] = 0;
x[2] = 0;
do i = 1 to npoints;
x[1] + w[i] * cvxhull[i,1];
x[2] + w[i] * cvxhull[i,2];
end;
/* write out x coordinates to second segment */
call WriteMember(selected,2,x);
/* compute objective value */
r = (4 - 2.1*x[1]**2 + x[1]**4/3)*x[1]**2 + x[1]*x[2] +
(-4 + 4*x[2]**2)*x[2]**2;
return(r);
endsub;
/*************************************/
subroutine gethistory(iteration, maxiter, popsize, iterArray[*], bestArray[*]);
outargs iteration, iterArray, bestArray;
iteration = iteration+1;
array objValues[1] /nosym;
/* dynamically allocate array to fit populationSize */
call dynamic_array(objValues, popsize);
/* read in current objective values */
call GetObjValues(objValues, popsize);
/* find best value */
current_best = objValues[1];
do i = 2 to popsize;
/* for a minimization problem, use < here */
if(objValues[i] < current_best) then
current_best = objValues[i];
end;
*put iteration current_best;
iterArray[iteration]=iteration;
bestArray[iteration]=current_best;
if (iteration = maxiter) then do;
put +1;
do i = 1 to maxiter;
put "iter=" iterArray[i] ", bestObj=" bestArray[i] +1;
end;
end;
endsub;
/************************************/
call SetObjFunc('sixhump',0);
array lower[1] /nosym;
array upper[1] /nosym;
call dynamic_array(lower, npoints);
call dynamic_array(upper, npoints);
do i = 1 to npoints;
lower[i] = 0;
upper[i] = 1;
end;
call SetBounds(lower, upper, 1);
array delta[3] /nosym (0.01 0.01 0.01);
call SetMut('delta', 'nchange', 1, 'delta', delta);
call SetMutProb(0.05);
call SetCross('Twopoint', 'alpha', 0.9);
call SetCrossProb(0.8);
call SetSel('tournament', 'size', 2);
call SetElite(3);
iteration=0;
popsize=20;
maxiter=40;
array iterArray[1] /nosym;
array bestArray[1] /nosym;
call dynamic_array(iterArray, maxiter+1);
call dynamic_array(bestArray, maxiter+1);
call SetUpdateRoutine('gethistory');
call Initialize('DEFAULT', popsize);
call ContinueFor(maxiter);
run;
Hi Davi,
PROC GA provides a hook for an update routine, called each iteration. You can use this to do things like report the iteration count and current best objective. Below is an example the prints the best objective each iteration to Output.
Best,
--Josh
OPTIONS NODATE NONUMBER;
TITLE "Iteration history";
TITLE "Iteration history output";
proc ga seed = 555;
call SetEncoding('R3R2');
npoints = 3;
array cvxhull[3,2] /nosym ( -2 0
0 2
2 -2 );
/* Objective function */
function sixhump(selected[*],cvxhull[*,*],npoints);
/* Function has global minimum value of -1.0316
* at x = {-0.0898 0.7126} and
* x = { 0.0898 -0.7126}
*/
array w[1] /nosym;
call dynamic_array(w,npoints);
array x[2] /nosym;
call ReadMember(selected,1,w);
/* make sure that weights add up to 1 */
sum = 0;
do i = 1 to npoints;
sum + w[i];
end;
/* if all weights 0, then reinitialize */
if sum=0 then do;
sum = npoints;
do i = 1 to npoints;
w[i] = 1;
end;
end;
/* re-normalize weights */
do i = 1 to npoints;
w[i] = w[i] / sum;
end;
call WriteMember(selected,1,w);
/* convert weights to x-coordinate form */
x[1] = 0;
x[2] = 0;
do i = 1 to npoints;
x[1] + w[i] * cvxhull[i,1];
x[2] + w[i] * cvxhull[i,2];
end;
/* write out x coordinates to second segment */
call WriteMember(selected,2,x);
/* compute objective value */
r = (4 - 2.1*x[1]**2 + x[1]**4/3)*x[1]**2 + x[1]*x[2] +
(-4 + 4*x[2]**2)*x[2]**2;
return(r);
endsub;
/*************************************/
subroutine gethistory(iteration, maxiter, popsize, iterArray[*], bestArray[*]);
outargs iteration, iterArray, bestArray;
iteration = iteration+1;
array objValues[1] /nosym;
/* dynamically allocate array to fit populationSize */
call dynamic_array(objValues, popsize);
/* read in current objective values */
call GetObjValues(objValues, popsize);
/* find best value */
current_best = objValues[1];
do i = 2 to popsize;
/* for a minimization problem, use < here */
if(objValues[i] < current_best) then
current_best = objValues[i];
end;
*put iteration current_best;
iterArray[iteration]=iteration;
bestArray[iteration]=current_best;
if (iteration = maxiter) then do;
put +1;
do i = 1 to maxiter;
put "iter=" iterArray[i] ", bestObj=" bestArray[i] +1;
end;
end;
endsub;
/************************************/
call SetObjFunc('sixhump',0);
array lower[1] /nosym;
array upper[1] /nosym;
call dynamic_array(lower, npoints);
call dynamic_array(upper, npoints);
do i = 1 to npoints;
lower[i] = 0;
upper[i] = 1;
end;
call SetBounds(lower, upper, 1);
array delta[3] /nosym (0.01 0.01 0.01);
call SetMut('delta', 'nchange', 1, 'delta', delta);
call SetMutProb(0.05);
call SetCross('Twopoint', 'alpha', 0.9);
call SetCrossProb(0.8);
call SetSel('tournament', 'size', 2);
call SetElite(3);
iteration=0;
popsize=20;
maxiter=40;
array iterArray[1] /nosym;
array bestArray[1] /nosym;
call dynamic_array(iterArray, maxiter+1);
call dynamic_array(bestArray, maxiter+1);
call SetUpdateRoutine('gethistory');
call Initialize('DEFAULT', popsize);
call ContinueFor(maxiter);
run;
Hi Josh,
I've already modified my code with your solution and it works perfectly.
Thanks for your help!
Best Regards,
Davi
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.