/** * Check if the problem have less of 100.000 permutation if it's the case we use the naive algorithm **/ bool is_easy_solution(const int k, const int n) { double fn, fk, fnk, ll, bino; fn = stirling_approx(n); fk = stirling_approx(k); fnk = stirling_approx(n-k); ll = log(100000); // limit heristic bino = fn - fk - fnk; int binomial = binomial_coef(n,k); if (n <= 1) { return true; } else { return bino *0.95 <= ll; } }
/* citrunc: truncate ci expansion * ------------------------------------------------------------------- * Input: * aelec = alpha electrons * belec = beta electrons * orbs = orbitals * nfrzc = number of frozen core orbitals * ndocc = number of doubly-occupied orbitals * nactv = number of active orbitals * nfrzv = number of frozen virtual orbitals * xlvl = excitation level * Output: * astr_len = number of alpha strings * bstr_len = number of beta strings * dtrm_len = number of determinants */ int citrunc(int aelec, int belec, int orbs, int nfrzc, int ndocc, int nactv, int nfrzv, int xlvl, int *astr_len, int *bstr_len, int *dtrm_len) { /* output scalar * err = error handling */ int err; /* local scalars * ci_orbs = orbitals - (frozen core) - (frozen virtual) * ci_aelec = aelec - (frozen core) * ci_belec = belec - (frozen core) * axdocc = alpha string docc orbital excitations * axactv = alpha string active orbital excitations * bxdocc = beta string docc orbital excitations * bxactv = beta string active orbital excitations * astrings = binomial_coef(ci_orbs, ci_aelec) * bstrings = binomial_coef(ci_orbs, ci_belec) * tot_dets = astrings * bstrings * aindx = alpha string index * bindx = beta string index */ int ci_orbs, ci_aelec, ci_belec; int axdocc, axactv, bxdocc, bxactv; int astrings, bstrings, tot_dets; int aindx, bindx; /* local arrays * astr1 = alpha string 1 * astr2 = alpha string 2 * bstr1 = beta string 1 * bstr2 = beta string 2 * bstr_hf = beta string start (Hartree-Fock) * astr_hf = alpha string start (Hartree-Fock) * detlstfl = determinant list file name * strlstfl = string list file name */ int *astr1, *astr2, *bstr1, *bstr2, *bstr_hf, *astr_hf; char detlstfl[FLNMSIZE], strlstfl[FLNMSIZE]; /* local linked-list * qindxlist = valid beta strings * pindxlist = valid alpha strings * detlist = valid determinants */ struct validstr *qindxlist; struct validstr *qptr, *tmp; struct validstr *pindxlist; struct validstr *pptr; struct validdet *detlist; struct validdet *dptr; /* local files * detfileptr = determinant list file pointer * strfileptr = string list file pointer */ FILE *detfileptr, *strfileptr; int i, j; /* initialize error flag */ err = 0; /* set determinant and string list file names */ strncpy(detlstfl, "det.list", FLNMSIZE); strncpy(strlstfl, "str.list", FLNMSIZE); /* compute electron numbers in truncated space */ ci_aelec = aelec - nfrzc; ci_belec = belec - nfrzc; ci_orbs = orbs - nfrzc - nfrzv; fprintf(stdout, " CI Expansion: %d %d %d\n", ci_aelec, ci_belec, ci_orbs); /* check input */ /* ndocc values */ if (ndocc > ci_belec) { fprintf(stderr, "*** ERROR: Unoccupied DOCC orbitals! ***\n"); err = -100; return err; } if (ci_orbs == 0 ) { fprintf(stderr, "WARNING: No virtual orbitals!\n"); err = 10; return err; } /* compute total, untruncated - excepting frozen core truncation - * number of alpha/beta/determinant strings */ astrings = binomial_coef(ci_orbs, ci_aelec); bstrings = binomial_coef(ci_orbs, ci_belec); tot_dets = astrings * bstrings; fprintf(stdout, "Untruncated expansion size = %10d\n", tot_dets); /* allocate arrays */ astr1 = (int *) malloc(ci_aelec * sizeof(int)); astr2 = (int *) malloc(ci_aelec * sizeof(int)); bstr1 = (int *) malloc(ci_belec * sizeof(int)); bstr2 = (int *) malloc(ci_belec * sizeof(int)); astr_hf = (int *) malloc(ci_aelec * sizeof(int)); bstr_hf = (int *) malloc(ci_belec * sizeof(int)); /* form HF strings */ for (i = 0; i < ci_aelec; i++) { astr_hf[i] = i + 1; astr1[i] = i + 1; } for (i = 0; i < ci_belec; i++) { bstr_hf[i] = i + 1; bstr1[i] = i + 1; } /* open determinant list file */ detfileptr = fopen("det.list", "w"); if (detfileptr == NULL) { fprintf(stderr, "*** ERROR: det.list could not be opened! ***\n"); exit(1); } /* open string list file */ strfileptr = fopen("str.list", "w"); if (strfileptr == NULL) { fprintf(stderr, "*** ERROR: str.list could not be opened! ***\n"); exit(1); } /* first strings are included */ aindx = str_adrfind(astr1, ci_aelec, ci_orbs); bindx = str_adrfind(bstr1, ci_belec, ci_orbs); fprintf(detfileptr, " %14d %14d\n", aindx, bindx); fprintf(strfileptr, "BETA\n"); fprintf(strfileptr, " %14d\n", bindx); *astr_len = 1; *bstr_len = 1; *dtrm_len = 1; /* allocate first node of valid q string linked list */ qindxlist = malloc(sizeof(struct validstr)); qindxlist->next = NULL; qptr = qindxlist; qptr->index = bindx; qptr->xdocc = 0; qptr->xactv = 0; qptr->next = malloc(sizeof(struct validstr)); qptr->next->next = NULL; qptr = qptr->next; /* allocate first node of valid p string linked list */ pindxlist = malloc(sizeof(struct validstr)); pindxlist->next = NULL; pptr = pindxlist; pptr->index = aindx; pptr->xdocc = 0; pptr->xactv = 0; pptr->next = malloc(sizeof(struct validstr)); pptr->next->next = NULL; pptr = pptr->next; /* allocate first node of valid determinant list */ detlist = malloc(sizeof(struct validdet)); detlist->next = NULL; dptr = detlist; dptr->pindx = 1; dptr->qindx = 1; dptr->next = malloc(sizeof(struct validdet)); dptr->next->next = NULL; dptr = dptr->next; /* first loop: |p,q> for p=1; q=1,..,bstrings */ for (i = 2; i <= bstrings; i++) { /* generate beta electron string */ str_strfind1(bstr1, ci_belec, ci_orbs, bstr2); /* test docc restrictions */ bxdocc = str_enfdocc(bstr2, ci_belec, ndocc, nactv); if (bxdocc > xlvl) { for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } continue; } /* test active orbital restrictions */ bxactv = str_enfactv(bstr2, ci_belec, ndocc, nactv); if (bxactv > xlvl) { for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } continue; } /* if here, string is valid */ *bstr_len = *bstr_len + 1; //fprintf(strfileptr, " %14d\n", i); *dtrm_len = *dtrm_len + 1; dptr->pindx = 1; dptr->qindx = i; //fprintf(detfileptr, " %14d %14d\n", 1, i); dptr->next = malloc(sizeof(struct validdet)); dptr->next->next = NULL; dptr = dptr->next; qptr->index = i; qptr->xdocc = bxdocc; qptr->xactv = bxactv; qptr->next = malloc(sizeof(struct validstr)); qptr->next->next = NULL; qptr = qptr->next; /* increment string */ for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } } /* second loop: |p,q> for p=1,..,astrings; q=1,..,bstrings */ fprintf(strfileptr, "ALPHA\n"); fprintf(strfileptr, " %14d\n", aindx); for (i = 2; i <= astrings; i++) { /* generate alpha electron string */ str_strfind1(astr1, ci_aelec, ci_orbs, astr2); /* test docc restrictions */ axdocc = str_enfdocc(astr2, ci_aelec, ndocc, nactv); if (axdocc > xlvl) { for (j = 0; j < ci_aelec; j++) { astr1[j] = astr2[j]; } continue; } /* test active orbital restrictions */ axactv = str_enfactv(astr2, ci_aelec, ndocc, nactv); if (axactv > xlvl) { for (j = 0; j < ci_aelec; j++) { astr1[j] = astr2[j]; } continue; } /* if here, |p, 1> is valid (p = i) */ //fprintf(strfileptr, " %14d\n", i); pptr->index = i; pptr->xdocc = axdocc; pptr->xactv = axactv; pptr->next = malloc(sizeof(struct validstr)); pptr->next->next = NULL; pptr = pptr->next; *astr_len = *astr_len + 1; for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr_hf[j]; } bindx = 1; /* now loop over valid beta strings */ qptr = qindxlist; while (qptr->next != NULL) { /* generate orbital string */ str_strfind2(bstr1, bindx, ci_belec, ci_orbs, qptr->index, bstr2); bindx = qptr->index; for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } /* test docc restrictions */ if ((axdocc + qptr->xdocc) > xlvl) { for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } qptr = qptr->next; continue; } /* test active orbital restrictions */ if ((axactv + qptr->xactv) > xlvl) { for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } qptr = qptr->next; continue; } /* test together */ if (((axactv + qptr->xactv) + (axdocc + qptr->xdocc)) > xlvl) { for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } qptr = qptr->next; continue; } /* if here, write determinant */ //fprintf(detfileptr, " %14d %14d\n", i, qptr->index); dptr->pindx = i; dptr->qindx = qptr->index; dptr->next = malloc(sizeof(struct validdet)); dptr->next->next = NULL; dptr = dptr->next; *dtrm_len = *dtrm_len + 1; for (j = 0; j < ci_belec; j++) { bstr1[j] = bstr2[j]; } qptr = qptr->next; } for (j = 0; j < ci_aelec; j++) { astr1[j] = astr2[j]; } } fprintf(stdout, "Deallocating electron arrays.\n"); free(astr1); free(astr2); free(bstr1); free(bstr2); free(bstr_hf); free(astr_hf); /* free linked list */ qptr = qindxlist; fprintf(stdout, "Deallocating linked list.\n"); while (qptr->next != NULL) { tmp = qptr; qptr = qptr->next; free(tmp); } fclose(detfileptr); fclose(strfileptr); return err; }
/** * Principal function of the Genetic Algorithm * \fn shooter_repartition genetic algorithm heuristic for selection of towers **/ void shooter_repartition(const char * input_file_name, const float mutation_prob, const int population_size, const int nb_children, const int nb_iteration, const int dist, float taux_var, bool sim) { vector<tower>* towers = new vector<tower>(); int k, n; tower_parse(input_file_name, *towers, k, n); srand((unsigned int) time(NULL)); if (!is_easy_solution(k, n)) { vector<vector<tower>*>* population = generate_initial_pop(towers, k, dist, taux_var); sort_population(population); vector<vector<tower>*>* children; // population growth until reaching population_size while ((int) population->size() < population_size) { children = reproduction_iteration(nb_children, mutation_prob, population, towers, dist, taux_var); sort_population(children); for (int i = 0; i < (int) children->size(); i++) { if ((int) population->size() < population_size) { //do not oversize the population_size && !find_indiv(population, (*children)[i]) population->push_back((*children)[i]); } else { break; } } } // reordering population sort_population(population); // iteration of genetic algorithm for (int j = 0; j < nb_iteration; j++) { children = reproduction_iteration(nb_children, mutation_prob, population, towers, dist, taux_var); for (int i = 0; i < (int) children->size(); i++) { child_insertion((*children)[i], population); } } // printing the results for (int i = 0; i < 10 ; i++) { cout << i+1 << " : "; print_indiv((*population)[i]); } if(sim) simulate_day(population->front(), towers, dist, taux_var); for (vector<vector<tower>*>::iterator it = population->begin(); it != population->end(); it++){ delete *it; } delete population; } else { // generate all the permutations and verify which is the best; int tmp_eval = 0, best_eval = 0; int nb_perm = binomial_coef(n,k); int t_size = towers->size(); int *perm_indexes = (int*) malloc( k * sizeof(int)); //build index tracker to avoid repeating indivs vector<tower> *tmp_indiv, *best_indiv; tmp_indiv = new vector<tower>(); best_indiv = new vector<tower>(); for(int l = 0; l<k; l++){ perm_indexes[l] = l; tmp_indiv->push_back((*towers)[l]); } // spread var for variance spread_indiv_var(tmp_indiv, towers, taux_var); *best_indiv = *tmp_indiv; best_eval = check_dist(best_indiv, dist) ? eval_indiv(best_indiv) : 0; for (int j = 0; j < nb_perm; j++){ //build and eval permutation for (int i = 0; i < k ; i++){ tmp_indiv->at(i) = towers->at(perm_indexes[i]); } spread_indiv_var(tmp_indiv, towers, taux_var); if(check_dist(tmp_indiv,dist)) { tmp_eval = eval_indiv(tmp_indiv); if (tmp_eval > best_eval) { best_eval = tmp_eval; *best_indiv = *tmp_indiv; } } //update of indexes tracker perm_indexes[k-1]++; for( int m = k-2; m >= 0; m--){ //go to next permutation if (perm_indexes[m+1] > t_size-(k-m-1)){ perm_indexes[m]++; for(int p = m+1; p < k; p++){//correcting overflow perm_indexes[p] = perm_indexes[p-1]+1; } } } } print_indiv(best_indiv); if (sim) simulate_day(best_indiv, towers, dist, taux_var); free(perm_indexes); delete best_indiv; delete tmp_indiv; } delete towers; }