Operations Research topics: SAS/OR,
SAS Optimization, and SAS Simulation Studio

[GA Optimization] Convergence Graph

Accepted Solution Solved
Reply
New Contributor
Posts: 4
Accepted Solution

[GA Optimization] Convergence Graph

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


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


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

 

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.
Thanks for your help!

Best Regards,
Davi

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

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