BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
DaviLaraia
Fluorite | Level 6

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

1 ACCEPTED SOLUTION

Accepted Solutions
joshgriffin
SAS Employee

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;
 

 

View solution in original post

2 REPLIES 2
joshgriffin
SAS Employee

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;
 

 

DaviLaraia
Fluorite | Level 6

Hi Josh,

 

I've already modified my code with your solution and it works perfectly.
Thanks for your help!

Best Regards,
Davi

SAS Innovate 2025: Register Now

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!

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.

Discussion stats
  • 2 replies
  • 1271 views
  • 1 like
  • 2 in conversation