Skip to content

How to add a new technique?

Gustavo Rosa edited this page Mar 23, 2017 · 5 revisions

If you want to add another optimization technique not implemented here, you can follow the steps below:

  1. Define a directive corresponding to your technique in opt.h (e.g. _PSO_ = 1 concerning Particle Swarm Optimization). Suppose we want to add Brazilian Soccer Optimization (BSO): we just need to add the following line in opt.h: #define _BSO_ X, where X stands for a natural number not used before.
  2. If your technique does need a different structure not implemented in LibOPT, you must do the following:
    1. All structures are implemented in include/common.h. Therefore, you should work on there first.
      1. At structure Agent, add your desired parameters. For instance, suppose BSO needs a player's strength for each decision variable: we need to add the following line:
      2. typedef struct Agent_{
          int n; /* number of decision variables */  
          double *x; /* position */  
          double *v; /* velocity */  
          double f; /* fitness value */  
          ...  
          double *strength; /* >>> NEW LINE HERE <<< */
        }Agent;
      3. At structure SearchSpace, add your desired parameters. For instance, suppose BSO uses an additional variable that encodes the quality of the grass during the match: we need to add the following line:
      4. typedef struct SearchSpace_{
          int m; /* number of agents (solutions) */
          int n; /* number of decision variables */
          Agent **a; /* array of pointers to agents */
          ...  
          double grass_quality; /* >>> NEW LINE HERE <<< */
        }SearchSpace;
    2. Now, we should move to src/common.c. There, you must allocate and deallocate your new variables as follows:
      1. At function CreateAgent, you should add one more switch command in order to allocate your new variable, as well as to initialize it:
      2. /* It creates an agent
        Parameters:
        n: number of decision variables
        opt_id: identifier of the optimization technique */
        Agent *CreateAgent(int n, int opt_id){
            if((n < 1) || opt_id < 1){
                fprintf(stderr,"\nInvalid parameters @CreateAgent.\n");
                return NULL;
            }
            
            Agent *a = NULL;
            a = (Agent *)malloc(sizeof(Agent));
            a->v = NULL;
            a->strength = NULL; /* >>> NEW LINE HERE <<< */
        
            switch (opt_id){
                case _PSO_:
                    a->v = (double *)malloc(n*sizeof(double));
                break;
                ...
                case _BSO_: /* >>> NEW CASE HERE <<< */
                    a->strength = (double *)malloc(n*sizeof(double));
                break;
                default:
                    free(a);
                    fprintf(stderr,"\nInvalid optimization identifier @CreateAgent\n");
                    return NULL;
                break;
            }
            
            a->x = (double *)malloc(n*sizeof(double));
            
            return a;
        }
      3. At function DestroyAgent, you should deallocate your new variable:
      4. /* It deallocates an agent
        Parameters:
        a: address of the agent to be deallocated
        opt_id: identifier of the optimization technique */
        void DestroyAgent(Agent **a, int opt_id){
            Agent *tmp = NULL;
        
            tmp = *a;
            if(!tmp){
                fprintf(stderr,"\nAgent not allocated @DestroyAgent.\n");
                exit(-1);
            }
            
            if(tmp->x) free(tmp->x);
            
            switch (opt_id){
                case _PSO_:
                    if(tmp->v) free(tmp->v);
                break;
                case _BSO_:
                    if(tmp->strength) free(tmp->strength); /* >>> DEALLOCATE YOUR VARIABLE HERE <<<*/
                break;   
                default:
                    fprintf(stderr,"\nInvalid optimization identifier @DestroyAgent.\n");
                break;     
            }
            
            free(tmp);
        }
      5. At function CreateSearchSpace, you should add one more switch command in order to allocate your new variable, as well as to initialize it. Notice you must do that only if your new variable is an array.
      6. /* It creates a search space
        Parameters:
        m: number of agents
        n: number of decision variables
        opt_id: identifier of the optimization technique */
        SearchSpace *CreateSearchSpace(int m, int n, int opt_id){
            SearchSpace *s = NULL;
            
            if((m < 1) || (n < 1) || (opt_id < 1)){
                fprintf(stderr,"\nInvalid parameters @CreateSearchSpace.\n");
                return NULL;
            }
            int i;
            
            s = (SearchSpace *)malloc(sizeof(SearchSpace));
            s->m = m;
            s->n = n;
            
            s->a = (Agent **)malloc(s->m*sizeof(Agent *));
            s->a[0] = CreateAgent(s->n, opt_id);
            if(s->a[0]){ /* Here, we verify whether opt_id is valid or not. In the latter case, function CreateAgent returns NULL. */
                for(i = 1; i < s->m; i++)
                    s->a[i] = CreateAgent(s->n, opt_id);
            }else{
                free(s->a);
                free(s);
                return NULL;
            }
            
            switch (opt_id){
                case _BSO_:
                    /* >>> NEW VARIABLE HERE <<<*/
                break;        
            }
            return s;
        }
      7. At function DestroySearchSpace, you should deallocate your new variable:
      8. /* It deallocates a search space
        Parameters:
        s: address of the search space to be deallocated
        opt_id: identifier of the optimization technique */
        void DestroySearchSpace(SearchSpace **s, int opt_id){
            SearchSpace *tmp = NULL;
            int i;
            
            tmp = *s;
            if(!tmp){
                fprintf(stderr,"\nSearch space not allocated @DestroySearchSpace.\n");
                exit(-1);
            }
            
            for(i = 0; i < tmp->m; i++)
                if(tmp->a[i]) DestroyAgent(&(tmp->a[i]), opt_id);
            free(tmp->a);
            
            switch (opt_id){
                case _BSO_:
                    /* >>> DEALLOCATE YOUR VARIABLE HERE <<<*/
                break;        
                default:
                    fprintf(stderr,"\nInvalid optimization identifier @DestroySearchSpace.\n");
                break;
            }
            
            free(tmp);
        }
  3. Further, you need to create files include/bso.h and src/bso.c. In regard to their headers, you must do as follows:
    1. in file include/bso.h:
       #ifndef BSO_H
       #define BSO_H
      
       #include opt.h
       ... /* >>> YOUR NEW CODE HERE <<< */
       #endif
    2. in file src/bso.c:
      #include "bso.h"
  4. Finally, you need to update Makefile in order to compile your new technique. You can just copy and paste the lines regarding any technique that has been written already.