double gaussian(double dSig,double dLim) { /* truncated Gaussian */ double dVal; do { dVal = dSig*randGaussian(); } while (dLim > 0.0 && fabs(dVal) > dLim*dSig); return dVal; }
/* It executes the Brain Storm Optimization for function minimization according to Algorithm 1 (El-Abd, 2017) Parameters: s: search space Evaluate: pointer to the function used to evaluate particles arg: list of additional arguments */ void runBSO(SearchSpace *s, prtFun Evaluate, ...) { va_list arg, argtmp; int i, j, z, k, t, *best = NULL, c1, c2, **ideas_per_cluster = NULL; double p, r; Agent *nidea = NULL; va_start(arg, Evaluate); va_copy(argtmp, arg); if (!s) { fprintf(stderr, "\nSearch space not allocated @runBSO.\n"); exit(-1); } ideas_per_cluster = (int **)malloc(s->k * sizeof(int *)); best = (int *)malloc(s->k * sizeof(int)); nidea = CreateAgent(s->n, _BSO_, _NOTENSOR_); EvaluateSearchSpace(s, _BSO_, Evaluate, arg); /* Initial evaluation */ for (t = 1; t <= s->iterations; t++) { fprintf(stderr, "\nRunning iteration %d/%d ... ", t, s->iterations); /* clustering ideas */ k_means(s, best, &ideas_per_cluster); /* for each idea */ for (i = 0; i < s->m; i++) { va_copy(arg, argtmp); p = GenerateUniformRandomNumber(0, 1); if (s->p_one_cluster > p) { c1 = (int)GenerateUniformRandomNumber(0, s->k); /* selecting a cluster probabilistically */ p = GenerateUniformRandomNumber(0, 1); /* creating a new idea based on the cluster selected previously. We also consider if cluster c1 has a single idea, i.e., ideas_per_cluster[c1][0] == 0. Notice we do not consider the cluster's center into that computation @kmeans function, which means a unitary cluster has ideas_per_cluster[c1][0] == 0. */ if ((s->p_one_center > p) || (ideas_per_cluster[c1][0] == 0)) { for (k = 0; k < s->n; k++) nidea->x[k] = s->a[best[c1]]->x[k]; } else { /* creating a new idea based on another idea j selected randomly from cluster c1 */ j = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c1][0]); j = ideas_per_cluster[c1][j]; for (k = 0; k < s->n; k++) nidea->x[k] = s->a[j]->x[k]; } } else { /* selecting two clusters' centers probabilistically */ c1 = (int)GenerateUniformRandomNumber(0, s->k); c2 = (int)GenerateUniformRandomNumber(0, s->k); /* selecting two ideas randomly */ if (ideas_per_cluster[c1][0] == 0) j = best[c1]; else { j = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c1][0]); j = ideas_per_cluster[c1][j]; } if (ideas_per_cluster[c2][0] == 0) z = best[c2]; else { z = (int)GenerateUniformRandomNumber(1, ideas_per_cluster[c2][0]); z = ideas_per_cluster[c2][z]; } p = GenerateUniformRandomNumber(0, 1); r = GenerateUniformRandomNumber(0, 1); /* it creates a new idea based on a random combination of two selected clusters' centers */ if (s->p_two_centers > p) { for (k = 0; k < s->n; k++) nidea->x[k] = r * s->a[best[c1]]->x[k] + (1 - r) * s->a[best[c2]]->x[k]; } else { /* it creates a new idea based on the ideas selected at random from the clusters previously chosen */ for (k = 0; k < s->n; k++) nidea->x[k] = r * s->a[j]->x[k] + (1 - r) * s->a[z]->x[k]; } } /* adding local noise to the new created idea */ p = (0.5 * s->iterations - t) / k; r = GenerateUniformRandomNumber(0, 1) * Logistic_Sigmoid(p); for (k = 0; k < s->n; k++) nidea->x[k] += r * randGaussian(0, 1); /* It evaluates the new created idea */ CheckAgentLimits(s, nidea); p = Evaluate(nidea, arg); if (p < s->a[i]->fit) { /* if the new idea is better than the current one */ for (k = 0; k < s->n; k++) s->a[i]->x[k] = nidea->x[k]; s->a[i]->fit = p; } if (s->a[i]->fit < s->gfit) s->gfit = s->a[i]->fit; } fprintf(stderr, "OK (minimum fitness value %lf)", s->gfit); for (i = 0; i < s->k; i++) free(ideas_per_cluster[i]); } free(ideas_per_cluster); free(best); DestroyAgent(&nidea, _BSO_); va_end(arg); }