Solved
New Contributor
Posts: 4

# [GA Optimization] Convergence Graph

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?

Best Regards,
Davi Laraia

Accepted Solutions
Solution
‎10-29-2015 04:35 PM
SAS Employee
Posts: 2

## Re: [GA Optimization] Convergence Graph

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

All Replies
Solution
‎10-29-2015 04:35 PM
SAS Employee
Posts: 2

## Re: [GA Optimization] Convergence Graph

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

New Contributor
Posts: 4

## Re: [GA Optimization] Convergence Graph

[ Edited ]

Hi Josh,

I've already modified my code with your solution and it works perfectly.