
#include "ilist.h"

#include "qsorter.h"
#include "scpview.h"
#include "ei_simplex.h"
#include "genetic.h"


NBGA* nbga_new(SCPView* pv,int populationSize,int maxIterations, double mutProbability,int lowerBound,int upperBound) {

    NBGA* n=NULL;


    /*Check parameters and conditions*/
    assert(pv!=NULL);

    /*Create new NBGA and check whether it is succesfull*/
    n = (NBGA*)malloc(sizeof(NBGA));
    assert(n!=NULL);

    /*Setup the NBGA*/
    n->genotypeLength=pv->rows;
    n->populationSize=populationSize;
    n->problemView=pv;
    n->maxIterations=maxIterations;
    n->iteration=0;
    n->mutationProbability=mutProbability;

    nbga_set_simplex_limits(n,300,300);

    /*Allocate table for population*/
    n->populationTable=(int*)malloc(sizeof(int)*n->genotypeLength*n->populationSize);
    assert(n->populationTable!=NULL);

    /*Sort columns according to their nonincreasing cost*/
    quick_sort_columns(n->problemView,nbga_compare_columns,NULL);

    /*Initialize N(i) sets*/
    nbga_initialize_row_cover(n,&n->rowCover,NULL);
    assert(&n->rowCover!=NULL);

    /*Statistics*/
    n->stCrossoverCounter=0;

    /*Widely used temporary phenotype*/
    n->f=(unsigned char*)malloc(n->problemView->columns);
    assert(n->f!=NULL);

    /*Temporary phenotypes used by crossover operation*/
    n->parent1Phenotype=(unsigned char*)malloc(n->problemView->columns);
    n->parent2Phenotype=(unsigned char*)malloc(n->problemView->columns);
    

    n->lowerBound=lowerBound;
    n->upperBound=upperBound;

    n->vcosts=(float*)malloc(n->populationSize*sizeof(float));
    n->probs=(float*)malloc(n->populationSize*sizeof(float));
    
    assert(n->vcosts!=NULL && n->probs!=NULL);

    /*Return*/
    return n;
}


void nbga_solve(NBGA* n) {

    int t;

    int parent1=0;
    int parent2=0;

    int cost2=0;
    int cost3=0;

    int* betterOffspring;

    int wkIndex=0;
    
    int* offspring=NULL;
    int* offspring2=NULL;
    int* offspring3=NULL;

    /*Check parameter*/
    assert(n!=NULL);

    offspring=(int*)malloc(n->genotypeLength*sizeof(int));
    offspring2=(int*)malloc(n->genotypeLength*sizeof(int));
    offspring3=(int*)malloc(n->genotypeLength*sizeof(int));

    assert(offspring!=NULL && offspring2!=NULL && offspring3!=NULL);

    

    /*STEP 1 CREATE INITIAL POPULATION
     *===============================================*/
    nbga_create_population(n);
   


    /*STEP 2 ITERATE THROUGH EVOLUTION
     *===============================================*/
    for (t=0;t<n->maxIterations;t++) {


        /*Choose parent genotypes by proportional selection. If there exist
          individual that reached lower bound, NBGA is terminated*/
        if (nbga_select_parents(n,&parent1,&parent2,&wkIndex)==1) break;
       

        /*Produce offspring using crossover operation*/
        nbga_crossover2(n,parent1,parent2,offspring);
        

        nbga_get_phenotype(n,offspring,n->f);
        assert(scp_view_is_solution(n->problemView,n->f)==1);

        /*Mutate genes of offspring*/
        nbga_mutation(n,offspring);
        
        nbga_get_phenotype(n,offspring,n->f);
        assert(scp_view_is_solution(n->problemView,n->f)==1);

        /*Apply greedy and dualgreedy, choose better result*/
        memcpy(offspring2,offspring,sizeof(int)*n->genotypeLength);
        memcpy(offspring3,offspring,sizeof(int)*n->genotypeLength);

        nbga_greedy(n,offspring2);
        nbga_prime(n,offspring2);
        nbga_dual_greedy(n,offspring3);
        
        cost2=nbga_get_genotype_cost(n,offspring2);
        cost3=nbga_get_genotype_cost(n,offspring3);

        betterOffspring=offspring2;
        if (cost3<cost2) betterOffspring=offspring3;

        /*Get phenotype and substitute the weakest individual*/
        nbga_substitute(n,wkIndex,betterOffspring,offspring);
        
        
    }

    free(offspring);
    free(offspring2);
    free(offspring3);

}


void nbga_prime(NBGA* n,int* genotype) {

    int i=0;
   
    int c=n->problemView->columns;
    int rv=0;
  
    /*Check parameters and conditions*/
    assert(n!=NULL);

    /*Create phenotype*/
    nbga_get_phenotype(n,genotype,n->f);
    
    /*Try to remove redundant columns*/
    for(i=0;i<c;i++) {
        /*Columns that do not form cover are omitted*/
        if (n->f[i]==0) continue;

        /*Check whether without column i we have still a solution
         *to the SCP
         */
        n->f[i]=0;
        rv=scp_view_is_solution(n->problemView,n->f);
        /*Without column i we do not have solution to SCP, column i
         *stays in the solution*/
        if (rv==0) n->f[i]=1;
    }

    /*Redundant columns were removed, we now modify the genotype according
     *to f[i]
     */
    nbga_find_alternative_columns(n,genotype,n->f);
   
    
}

void nbga_get_phenotype(NBGA* n,int* genotype,unsigned char* retMask) {

    int j=0;

    /*Check parameters and conditions*/
    assert (n!=NULL);
    assert (genotype!=NULL);
    assert (retMask!=NULL);

    /*Clear the retArray*/
    memset(retMask,0,n->problemView->columns);
    
    /*Fill the retArray*/
    for(j=0;j<n->genotypeLength;j++) {
        retMask[genotype[j]]=1;
    }

    
}


void nbga_dual_greedy(NBGA* n,int* genotype) {

    int c=0;
    int r=0;
    int i=0;
    int j=0;
    int v=0;
    
   
    double ratio;
    double maxRatio;
 
    RowCover rc2;
    unsigned char* rowMask;
    unsigned char* columnMask;

    int fCount;
    int jIndex;

    /*Check parameters and conditions*/
    assert (n!=NULL && genotype!=NULL);

    c=n->problemView->columns;
    r=n->problemView->rows;
    
    /*Create phenotype*/
    
    nbga_get_phenotype(n,genotype,n->f);
    fCount=0;
    for(i=0;i<c;i++) {
        if (n->f[i]==1) fCount++;
    }

    /*Create specific RowCover for our genotype*/
    nbga_initialize_row_cover(n,&rc2,n->f);

    /*Create rowMask filled with ones*/
    rowMask=(unsigned char*)malloc(r*sizeof(unsigned char));
    assert(rowMask!=NULL);
    memset(rowMask,1,r);
    
    /*Create columnMask filled with zeroes*/
    columnMask=(unsigned char*)malloc(c*sizeof(unsigned char));
    assert(columnMask!=NULL);
    memset(columnMask,0,c);


    /*CONSOLIDATION:
     *rc2         N(i)d (vector of vectors representation)
     *rowMask     Md    (mask representation)
     *f           Nd,Jd (mask representation)
     *columnMask  J     (mask representation)
     */

    while(fCount>0) {

        /*If there is a row in Md such that |N(i)d|=1, then add that column j
         *to the cover J. Simply said, a row that can be covered using only
          one column*/
        jIndex=-1;

        for(i=0;i<r;i++) {

            v=rc2.columnIndices[i]->length;
            if (v==1 && rowMask[i]==1) {
                /*What column covers i(th) row ?*/
                jIndex=ilist_get(rc2.columnIndices[i],0);
                /*J:=J union {j}*/
                columnMask[jIndex]=1;
                /*Remove all rows covered by such column from rowMask*/
                for(j=0;j<r;j++) {
                    if (rowMask[j]==1 && scp_view_get(n->problemView,j,jIndex)==1) {
                        rowMask[j]=0;
                    }
                }
                /*Break*/
                break;
            }
        }

        /*If there is no such column, we select a column with maximum
          ratio = cost/(size of intersection: rows coverd by column and rows remaining*/
        if (jIndex==-1) {
            maxRatio=0.0;
            for(i=0;i<c;i++) {
                if (n->f[i]==0) continue;

                ratio=scp_view_get_cost(n->problemView,i);
                ratio/=scp_view_get_1c_mask_intersect_size(n->problemView,rowMask,i);
                
                if (ratio>maxRatio) {
                    jIndex=i;
                    maxRatio=ratio;
                }
            }
        }

        /*Update Jd*/
        if (n->f[jIndex]==1) {
            fCount--;
        }
        n->f[jIndex]=0;


        /*Update RowCover. Remove column jIndex from all N(i) sets. Slow !*/
        for(i=0;i<r;i++) {
            ilist_start_iteration(rc2.columnIndices[i]);
            while(ilist_iterate(rc2.columnIndices[i],&v)) {
                if (v==jIndex) {
                    ilist_remove(rc2.columnIndices[i],rc2.columnIndices[i]->lastIterIndex);
                    break;
                }
            }
        }
        
    }   /*End of outer WHILE loop*/
    
    /*Now a dualgreedy algorithm is finished. We now have original genotype
     *and a columnMask. We modify genotype according to a new column mask
     */
    nbga_find_alternative_columns(n,genotype,columnMask);

    /*Freeing allocated resources*/
    nbga_delete_row_cover(n,&rc2);
    free(rowMask);
    free(columnMask);

    /*Done*/
    
}


void nbga_greedy(NBGA* n,int* genotype) {

    int c=0;
    int i=0;
    SCPView* gdView=NULL;
    GreedySolver* gs=NULL;
    IList* fixedList=NULL;


    /*Check parameters and conditions*/
    assert (n!=NULL && genotype!=NULL);

    c=n->problemView->columns;

    /*We perform greedy algorithm on a sub SCP defined by phenotype
     *of selected genotype*/
    nbga_get_phenotype(n,genotype,n->f);

    /*It is sure that phenotype has always at least one column*/
    gdView=scp_view_get_column_mask_subview(n->problemView,n->f,1);
    assert(gdView!=NULL);

    
    fixedList=scp_view_remove_fixed_columns(&gdView);
    memset(n->f,0,c);

    /*If view was not reduced into nothing, we perform greedy*/
    if (gdView!=NULL) {

        /*Performing Greedy on partial solution*/
        gs = greedy_solver_new(gdView);
        greedy_solver_initialize(gs,n->f);
        greedy_solver_solve_chvatal(gs,NULL);

        for(i=0;i<gdView->columns;i++) {
            n->f[gdView->parentColumnMap[i]]=gs->columnMask[i];
        }
    }
    /*Restoring fixed columns using the list*/
    ilist_start_iteration(fixedList);
    while(ilist_iterate(fixedList,&i)) {
        n->f[i]=1;
    }

    ilist_delete(fixedList);


    nbga_find_alternative_columns(n,genotype,n->f);

    /*Freeing allocated resources*/
    greedy_solver_delete(gs);
    scp_view_delete(gdView);

    /*Done*/
    
    
}

void nbga_mutation(NBGA* n,int* genotype) {

    int i=0;
    int j=0;
    int c=0;
    double tmp;
    double rn;

    float* prob=NULL;

    /*Check parameters and conditions*/
    assert(n!=NULL && genotype!=NULL);

    /*Probability vector*/
    c=n->problemView->columns;
    prob=malloc(sizeof(float)*c);
    assert(prob!=NULL);


    for(i=0;i<n->genotypeLength;i++) {

        j=rand()%131072;
        rn=(double)j/131072.0;
        if (rn>=n->mutationProbability) continue;

        ilist_start_iteration(n->rowCover.columnIndices[i]);
        tmp=0.0;
        while(ilist_iterate(n->rowCover.columnIndices[i],&j)) {
           tmp+=1.0/(double)scp_view_get_cost(n->problemView,j);
        }

        ilist_start_iteration(n->rowCover.columnIndices[i]);
        while(ilist_iterate(n->rowCover.columnIndices[i],&j)) {
            prob[j]=(float)((1.0/scp_view_get_cost(n->problemView,j))/tmp);
        }
        /*Now we have probabilities for columns from N(i), we have to choose the column*/
        j=rand()%131072;
        rn=(double)j/131072.0;

        /*rn is now <0,1>*/
        tmp=0.0;
        ilist_start_iteration(n->rowCover.columnIndices[i]);
        while(ilist_iterate(n->rowCover.columnIndices[i],&j)) {
            tmp+=prob[j];
            if (rn<tmp) {
                genotype[i]=j;
                break;
            }
        }
    }

    /*Done*/
    free(prob);
    

}


void nbga_crossover2(NBGA* n,int z1,int z2,int* retGenotype) {

    int i=0,j=0;
    int cols=n->problemView->columns;
    int c=0;

    int* g1Ptr=NULL;
    int* g2Ptr=NULL;

    double rhsVal=0.0;

    SCPView* commonColumnsView=NULL;
    IList* fixedList;
    EISimplex* simplex=NULL;


    g1Ptr=nbga_table_get_individual_ptr(n,z1);
    g2Ptr=nbga_table_get_individual_ptr(n,z2);

    nbga_get_phenotype(n,g1Ptr,n->parent1Phenotype);
    nbga_get_phenotype(n,g2Ptr,n->parent2Phenotype);

    
    /*Using columns common to the two genotypes, merged into first
     *phenotype
     */
    for(i=0;i<cols;i++) {
        if (n->parent2Phenotype[i]==1) n->parent1Phenotype[i]=1;
    }

    assert(scp_view_is_solution(n->problemView,n->parent1Phenotype)==1);

    commonColumnsView=scp_view_get_column_mask_subview(n->problemView,n->parent1Phenotype,1);
    assert(commonColumnsView!=NULL);

    /*Clearing the parent1Phenotype*/
    memset(n->parent1Phenotype,0,cols);

    /*From the view that contain only common columns we remove fixed columns and
     *also rows covered by these columns
     *NOTE List is mapped to the n->problemView
     */
   

    fixedList=scp_view_remove_fixed_columns(&commonColumnsView);

    /*Solve the subproblem (if exists) using simplex method*/
    if (commonColumnsView!=NULL) {
        if (commonColumnsView->rows<n->maxRowsForSimplex) {

            simplex=ei_simplex_new();

            if (ei_simplex_solve_scp(simplex,commonColumnsView,n->maxSimplexIterations)!=EI_SIMPLEX_OPTIMUM) {
                goto no_offspring_found;
            }
        
            for(i=0;i<commonColumnsView->columns;i++) {
                ei_simplex_get_rhs(simplex,i,&rhsVal);
                if (rhsVal!=floor(rhsVal)) goto no_offspring_found;
                n->parent1Phenotype[commonColumnsView->parentColumnMap[i]]=(int)rhsVal;
            }
        }
        else {
            goto no_offspring_found;
        }
    }
    
    /*Fixed columns are returned back the phenotype*/
    ilist_start_iteration(fixedList);
    while(ilist_iterate(fixedList,&i)) {
        n->parent1Phenotype[i]=1;
    }

    assert(scp_view_is_solution(n->problemView,n->parent1Phenotype)==1);
   
    /*Now in parent1Phenotype, there is phenotype of the new individual. Our problem
     *is now to create appropriate genotype. For each row we try to find a column
     *that covers it and is also part of this genotype
     */
    ilist_delete(fixedList);

    
    fixedList=ilist_new_from_mask(n->parent1Phenotype,cols,1);

    for(j=0;j<n->genotypeLength;j++) {

        ilist_start_iteration(fixedList);
        while(ilist_iterate(fixedList,&c)==1) {
            if (scp_view_get(n->problemView,j,c)==1) {
                retGenotype[j]=c;break;
            }
        }
    }

    
    n->stCrossoverCounter++;

    goto done;

    /*If no feasible offspring found, first parent is returned*/
    no_offspring_found:
    memcpy(retGenotype,g1Ptr,sizeof(int)*n->genotypeLength);

    /*Done*/
    done:
    ilist_delete(fixedList);
    if (simplex!=NULL) ei_simplex_delete(simplex);
    if (commonColumnsView!=NULL) scp_view_delete(commonColumnsView);
    

}


void nbga_initialize_row_cover(NBGA* n,RowCover* rc,unsigned char* mask) {

    int i=0;
    int j=0;
    int r=0;
    int c=0;
    int v=0;
    int k=0;

    /*Allocate space for column indices - basic*/
    rc->columnIndices=(IList**)malloc(sizeof(IList*)*n->problemView->rows);
    assert(rc->columnIndices!=NULL);

    /*Allocate strips for column indices. Little bit slow, but done
     *only once*/
     r=n->problemView->rows;
     c=n->problemView->columns;

    /*For each row*/
    for(i=0;i<r;i++) {
        /*Allocate space for column strip*/
        rc->columnIndices[i]=ilist_new();
        /*Fill the columns strip*/
        v=0;
        for(j=0;j<c;j++) {
            if ((scp_view_get(n->problemView,i,j)==1) & ((mask==NULL || mask[j]==1))) {
                ilist_append(rc->columnIndices[i],j);
            }
        }
        
    }

    /*Now we check whether the problem is unicost or multicost*/
    j=0;
    for(i=0;i<c;i++) {
        v=scp_view_get_cost(n->problemView,i);
        if (v!=1) {
            j=1;break;
        }
    }

    /*Not unicost, core refinement, only 10 cheapest columns will be kept*/
    if (j==1) {
        for(i=0;i<r;i++) {
            v=rc->columnIndices[i]->length;
            if (v>10) {
                for(k=0;k<v-10;k++) {
                    ilist_remove(rc->columnIndices[i],0);
                }
            }
        }
    }
    

}


void nbga_create_population(NBGA* n) {

    int i=0;
    int j=0;
    int v=0;
    int k=0;

    /*Check parameters and conditions*/
    assert(n!=NULL);

    for(j=0;j<n->populationSize;j++) {

        /*For each row i choose random column from N(i)*/
        for(i=0;i<n->genotypeLength;i++) {
            v=n->rowCover.columnIndices[i]->length;
            /*Random number from <0,v-1>*/
            k=rand()%v;
            /*Put it to the table*/
            nbga_table_put(n,j,i,ilist_get(n->rowCover.columnIndices[i],k));
        }
    }

    /*Apply Prime redundant column elimination*/
    for (j=0;j<n->populationSize;j++) {
        nbga_prime(n,n->populationTable+j*n->genotypeLength);
    }
   

}


void nbga_find_alternative_columns(NBGA* n,int* genotype,unsigned char* mask) {

    int i=0;
    int v=0;
    int p=0;
    int j=0;

    for(i=0;i<n->genotypeLength;i++) {
        /*Row i is covered by column v*/
        v=genotype[i];
        /*If column v remains in the cover, we continue*/
        if (mask[v]==1) continue;

        /*If column was removed from the cover, we have to choose alternative*/
        ilist_start_deteration(n->rowCover.columnIndices[i]);
        p=-1;
        while(ilist_deterate(n->rowCover.columnIndices[i],&j)) {
            if (mask[j]==1) genotype[i]=j;
            p=0;
            break;
        }
        /*Sanity check*/
        assert (p!=-1);
    }
}

void nbga_table_put(NBGA* n,int individualIndex,int geneIndex,int value) {

    int* ptr=NULL;

    /*Check parameters and conditions*/
    assert(n!=NULL);
    assert(individualIndex>=0 && individualIndex<n->populationSize && geneIndex>=0 && geneIndex<n->genotypeLength);
    

    /*Put that value*/
    ptr = n->populationTable+individualIndex*n->genotypeLength+geneIndex;
    *ptr=value;

    /*Done*/
    
}

int* nbga_table_get_individual_ptr(NBGA* n,int individualIndex) {

    /*Check parameters*/
    assert(n!=NULL);
    assert(individualIndex>=0 && individualIndex<n->populationSize);

    /*Get pointer*/
    return n->populationTable+individualIndex*n->genotypeLength;

}

void nbga_set_simplex_limits(NBGA* n,int maxRows,int maxIterations) {

    /*Check parameters and conditions*/
    assert(n!=NULL);
    assert(maxRows>=0 && maxIterations>=0);

    /*Set values*/
    n->maxRowsForSimplex=maxRows;
    n->maxSimplexIterations=maxIterations;

    /*Done*/
    
}



int nbga_get_genotype_cost(NBGA* n,int* genotype) {

    int cost=0;
    int i;
    int c=0;
    

    /*Check parameters and conditions*/
    assert (n!=NULL && genotype!=NULL);

    /*Get phenotype*/
    c = n->problemView->columns;
   
    nbga_get_phenotype(n,genotype,n->f);

    for(i=0;i<c;i++) {
        if (n->f[i]==1) cost+=scp_view_get_cost(n->problemView,i);
    }
    
    return cost;

}

int nbga_select_parents(NBGA* n,int *p1,int *p2,int* weakestIndex) {

    int maxCost=0;
    int lastCost=0;
    int i,j;
    double rn,tmp;
    double divisor=0.0;
    
    /*Check parameters and conditions*/
    assert (n!=NULL && p1!=NULL && p2!=NULL && weakestIndex!=NULL);

    for(i=0;i<n->populationSize;i++) {
        n->vcosts[i]=(float)nbga_get_genotype_cost(n,n->populationTable+i*n->genotypeLength);
        if (n->vcosts[i]>maxCost) {
            maxCost=(int)n->vcosts[i];
            *weakestIndex=i;
        }
        /*Lower bound reached ??*/
        if (n->vcosts[i]<=n->lowerBound) return 1;
    }

    lastCost=scp_view_get_cost(n->problemView,n->problemView->columns-1);

    
    /*Our vector of costs will change into vector of fitness functions*/
    for(i=0;i<n->populationSize;i++) {
        n->vcosts[i]=-n->vcosts[i];
        n->vcosts[i]+=maxCost;
        n->vcosts[i]+=lastCost;
        divisor+=(double)n->vcosts[i];
    }

    /*Verify divisor*/
    assert(divisor!=0.0);

    /*Vector of probabilities*/
    for(i=0;i<n->populationSize;i++) {
        n->probs[i]=(double)n->vcosts[i]/divisor;
        /*printf("Fitness: %f, Probability: %f,Cost:%d\n",n->vcosts[i],n->probs[i],nbga_get_genotype_cost(n,nbga_table_get_individual_ptr(n,i)));*/
    }

   
    j=rand()%800000;
    rn=(double)j/800000.0;
    
    /*rn is now <0,1>*/
    tmp=0.0;
    for(j=0;j<n->populationSize;j++) {
        tmp+=n->probs[j];
        if (rn<tmp) {
           *p1=j;
           break;
        }
    }

    j=rand()%800000;
    rn=(double)j/800000.0;
    
    /*rn is now <0,1>*/
    tmp=0.0;
    for(j=0;j<n->populationSize;j++) {
        tmp+=n->probs[j];
        if (rn<tmp) {
           *p2=j;
           break;
        }
    }

    return 0;
    
    
}


void nbga_substitute(NBGA* n,int index,int* greedyOffspring,int* offspring) {

    int i=0;
    int j=0;
    int k=0;
    int c=0;
    unsigned char* gf=NULL;
    unsigned char* f=NULL;

    /*Check parameters and conditions*/
    assert (n!=NULL && greedyOffspring!=NULL && offspring!=NULL);
    assert (index>=0);

    /*Compare phenotypes*/
    c = n->problemView->columns;

    gf=(unsigned char*)malloc(c);
    f=(unsigned char*)malloc(c);

    assert(gf!=NULL && f!=NULL);

    nbga_get_phenotype(n,greedyOffspring,gf);

    for(i=0;i<n->populationSize;i++) {
        nbga_get_phenotype(n,n->populationTable+i*n->genotypeLength,f);
        k=0;
        for(j=0;j<c;j++) {
            if (gf[j]==f[j]) k++;
        }
        /*There is individual with same phenotype, we put original offspring
         to the population*/
        if (k==c) {
            memcpy(n->populationTable+index*n->genotypeLength,offspring,sizeof(int)*n->genotypeLength);
            goto f_end;
        }
    }

    /*There is no individual with same phenotype, we put greedyOffspring to
     *the population*/

     memcpy(n->populationTable+index*n->genotypeLength,greedyOffspring,sizeof(int)*n->genotypeLength);

     f_end:
     free(gf);
     free(f);
     return;

}


void nbga_get_solution(NBGA* n,unsigned char* retMask) {

    int i=0;
    int min=PS_INFINITY;
    int k=0;
    int minIndex=-1;

    /*Check parameters*/
    assert(n!=NULL);
    assert(retMask!=NULL);

    /*Find cheapest genotype*/
    for(i=0;i<n->populationSize;i++) {
        k=nbga_get_genotype_cost(n,nbga_table_get_individual_ptr(n,i));
        if (k<min) {
            min=k;
            minIndex=i;
        }
    }
    
    /*Fill retArray*/
    nbga_get_phenotype(n,nbga_table_get_individual_ptr(n,minIndex),retMask);

}

void nbga_print(NBGA* n) {

    int i=0;
    int j=0;
    int v=0;


    printf("[NBGA] {\n");

    /*Check parameters and conditions*/
    if (n==NULL) {
        printf("!!! NULL !!!\n}\n");
        return;
    }

    /*Print NBGA state*/
    printf("Population size: %d, Max. Iterations: %d\n",n->populationSize,n->maxIterations);
    printf("Current iteration: %d\n",n->iteration);

    printf("Population table:\n");
    for (i=0;i<n->populationSize;i++) {
        for(j=0;j<n->genotypeLength;j++) {
            v=*(n->populationTable+i*n->genotypeLength+j);
            printf("%02d,",v);
        }
        printf("\n");
    }

    printf("N(i) sets:\n");
    for(i=0;i<n->problemView->rows;i++) {
        ilist_print(n->rowCover.columnIndices[i]);
    }

    printf("}\n");

}

void nbga_delete_row_cover(NBGA* n,RowCover* rc) {

    int i=0;
    IList* ptr;

    /*Check parameters and conditions*/
    assert (rc!=NULL);

    /*For each row*/
    for(i=0;i<n->genotypeLength;i++) {
        ptr=rc->columnIndices[i];
        ilist_delete(ptr);
    }

    /*Free the rest*/
    free(rc->columnIndices);
    
}

int nbga_compare_columns(SCPView* v,int c1,int c2,void* miscData) {

    int v1;
    int v2;
    v1=scp_view_get_cost(v,c1);
    v2=scp_view_get_cost(v,c2);

    if (v1>v2) return -1; else if (v1<v2) return +1;
    return 0;

}

void nbga_delete(NBGA* n) {

    /*Check parameters and conditions*/
    if (n==NULL) return;

    /*Delete internal structures*/
    nbga_delete_row_cover(n,&n->rowCover);
    if (n->populationTable!=NULL) free(n->populationTable);
    if (n->f!=NULL) free(n->f);
    if (n->parent1Phenotype!=NULL) free(n->parent1Phenotype);
    if (n->parent2Phenotype!=NULL) free(n->parent2Phenotype);
    if (n->probs!=NULL) free(n->probs);
    if (n->vcosts!=NULL) free(n->vcosts);

    /*Delete NBGA*/
    free(n);
    
}

