#ifndef _GENETIC_H
#define	_GENETIC_H

#include "common.h"
#include "ei_simplex.h"
#include "scproblem.h"
#include "greedy.h"



#ifdef	__cplusplus
extern "C" {
#endif

#define NBGA_OK 0
#define NBGA_FAILURE -1

#define NBGA_SP_INTOPT 2
#define NBGA_SP_NOFEAS 3

/** \defgroup NBGA Non-binary genethic algorithm for SCP
 *@{
 */

   
typedef struct _NBGA NBGA;
typedef struct _RowCover RowCover;


/** \brief RowCover maintains information about row coverage
 *   For each row, there is a list of columns that cover the row
*/
struct _RowCover {
    IList** columnIndices;
};

/** \brief NGBA*/
struct _NBGA {

    /** \brief View to the underlying problem*/
    SCPView* problemView;
    /** \brief Population table. In this variant of GA, population
     * has constant number of members*/
    int* populationTable;
    /** \brief Number of population members*/
    int populationSize;
    /** \brief Length of genotype - it is a number of rows*/
    int genotypeLength;
    /** \brief Current iteration*/
    int iteration;
    /** \brief Maximum number of iterations allowed*/
    int maxIterations;
    /** \brief For each row, there is a list of columns that cover the row*/
    RowCover rowCover;

    /** \brief Mutation probability
     *   Probability of mutation of each gene of the genotype
     */
    double mutationProbability;

    /** \brief Maximum number of rows that can enter simplex method during crossover*/
    int maxRowsForSimplex;

    /** \brief Maximum number of simplex method iterations*/
    int maxSimplexIterations;

    /** \brief How many successfull crosovers performed*/
    int stCrossoverCounter;

    /** \brief Widely used temporary phenotype*/
    unsigned char* f;
    unsigned char* parent1Phenotype;
    unsigned char* parent2Phenotype;

    /** \brief Lower bound of the cost of the cover. If individual reach
     *   this bound, NBGA ends*/
    int lowerBound;

    /** \brief Upper bound of the cost of the cover*/
    int upperBound;

    /** \brief Temporary vector of costs*/
    float* vcosts;

    /** \brief Temporary vector of probabilities*/
    float* probs;

};



/** \brief Create new NBGA
 *  \param p View to the underlying problem that will be solved
 *  \param populationSize Size of the population
 *  \param maxIterations Maximum number of iterations
 *  \param mutProbability Mutation probability
 *  \param lowerBound Lower bound of the cost of the solution
 *  \param upperBound Upper bound of the cost of the solution
 *  \return Newly created NBGA or NULL
 */
NBGA* nbga_new(SCPView* pv,int populationSize,int maxIterations,double mutProbability,int lowerBound,int upperBound);


/** \brief Create initial random population
 */
void nbga_create_population(NBGA* n);

/** \brief Apply Prime algorithm to specified genotype
 *  \param genotype affected genotype
 */
void nbga_prime(NBGA* n,int* genotype);


/** \brief Apply mutation to selected genotype
 *  \param genotype Genotype to be mutated
 */
void nbga_mutation(NBGA*n,int* genotype);


/** \brief Apply crossover
 *  \param z1 Index of first genotype
 *  \param z2 Index of second genotype
 *  \param retGenotype Returned offspring's genotype. Must point to allocated memory
 */
void nbga_crossover2(NBGA*n,int z1,int z2,int* retGenotype);

/** \brief Unusde dumb implementation of crossover*/
void nbga_crossover(NBGA*n,int z1,int z2,int* retGenotype);

/** \brief Get phenotype of selected genotype
 *  \param genotype Genotype for which phenotype is calculated
 *  \param retMask Place for the result will be placed. Must point to
 *   allocated memory
 */
void nbga_get_phenotype(NBGA* n,int* genotype,unsigned char* phenotype);

/** \brief Put gene to the population table
 *  \param individualIndex Index of affected individual
 *  \param geneIndex Index of gene
 */
void nbga_table_put(NBGA* n,int individualIndex,int geneIndex,int value);

/** \brief Initialize RowCover
 *  \param rc RowCover that will be initialized
 *  \param mask Indicates what columns will form the RowCover. Can be
 *   set to NULL to indicate all columns
 */
void nbga_initialize_row_cover(NBGA* n,RowCover* rc,unsigned char* mask);


/** \brief Find alternative columns according to specified column mask.
 *  If genotype contain columns that are not present in the specified mask,
 *  alternative columns using RowCover are found.
 *  \param genotype Genotype
 *  \param mask Column mask
 *  
 */
void nbga_find_alternative_columns(NBGA* n,int* genotype,unsigned char* mask);

/** \brief Apply Dual greedy algorithm to specified genotype
 *  \param genotype Affected genotype
 *  
 */
void nbga_dual_greedy(NBGA* n,int* genotype);


/** \brief Apply Greedy algorithm to specified genotype
 *  \param genotype Affected genotype
 */
void nbga_greedy(NBGA* n,int* genotype);

/** \brief Solve the SCP using NBGA
 */
void nbga_solve(NBGA* n);

/** \brief Select parents for crossover using proportional selection
 *  \param weakestIndex There will be returned index of weakest individual
 *  \param p1 There will be returned index of first parent
 *  \param p2 There will be returned index of second parent
 *  \return 0 when normal selection performed, 1 when individual representing
 *   optimal solution was found
 */
int nbga_select_parents(NBGA* n,int *p1,int *p2,int* weakestIndex);

/** \brief Substitute individual with other individuals
 *  \param index Index of individual that will leave the population
 *  \param greedyOffspring Genotype of individual that is result of crossover
 *   operation and Greedy or DualGreedy redundant column elimination
 *  \param offspring Genotype of individual that is result of crossover
 *   operation
 */
void nbga_substitute(NBGA* n,int index,int* greedyOffspring,int* offspring);

/** \brief Get cost of specified genotype
 *  \param genotype Genotype
 *  \return Nonnegative cost
 */
int nbga_get_genotype_cost(NBGA* n,int* genotype);


/** \brief Get pointer to the first gene of specified individual
 *  \param individualIndex index of individual
 *  \return Pointer to first gene
 */
int* nbga_table_get_individual_ptr(NBGA* n,int individualIndex);

/** \brief Perform simplex method on subproblem created during crossover
 *   operator
 *   \return NBGA_SP_INTOPT or NBGA_SP_NOFEAS
 */
int nbga_crossover_do_simplex(NBGA* n,SCPView* subProblem,unsigned char* retMask);


/** \brief Set limits for simplex method used by crossover operation
 *  \param maxRows Maximum number of rows that can enter simplex method
 *  \param maxIterations Maximum number of simplex method iterations
 *  
 */
void nbga_set_simplex_limits(NBGA* n,int maxRows,int maxIterations);


/** \brief Get best solution (cheapest individual)
 *  \param retMask Pointer to allocated memory, where column mask is returned
 */
void nbga_get_solution(NBGA* n,unsigned char* retMask);


/** \brief Supplementary comparation function*/
int nbga_compare_columns(SCPView* v,int c1,int c2,void* miscData);

/** \brief Print state of NBGA*/
void nbga_print(NBGA* n);

/** \brief Delete RowCover
 *  \param rc RowCover that will be deleted
 */
void nbga_delete_row_cover(NBGA* n,RowCover* rc);

/** \brief Delete NBGA*/
void nbga_delete(NBGA* n);




#ifdef	__cplusplus
}
#endif

#endif	/* _GENETIC_H */


/** @}*/
