Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C] [C++] Generowanie zmiennoprzecinkowych liczb losowych z dużą dokładnością do algorytmu genetycznego

Ostatnio zmodyfikowano 2017-06-20 00:17
Autor Wiadomość
ignacy.z
Temat założony przez niniejszego użytkownika
[C] [C++] Generowanie zmiennoprzecinkowych liczb losowych z dużą dokładnością do algorytmu genetycznego
» 2017-06-19 23:44:23
Witam, edytuję program opierający swoje działanie na algorytmie genetycznym. Ma on za zadanie znaleźć lokalne minimum zadanej funkcji. Aby zbadać parametry przy których żadna dokładność jest osiągnięta i nie opłaca się robić większych obliczeń potrzebuje zmiennoprzecinkowych liczb losowych z przedziału (-2, 2) w X i Y (z góry zadany przedział). W celu generacji tych liczb używam funkcji:

C/C++
double randval( double low, double high )
{
    double val;
    val =(( double )( rand() % 10000 ) / 10000.0 ) *( high - low ) + low;
    printf( "%.9f\t", val );
   
    return( val );
}

Z tego co zrozumiałem to zwiększanie dokładności odbywa się przez zwiększenie ilości zer przy dzieleniu modulo. Jednak zwiększenie ilości zer powoduje zwracanie coraz mniejszych liczb w zmiennej val. Czy umie ktoś powiedzieć jak przeprowadzić takie losowanie liczb losowych żeby liczby z zadanego przedziału miały dokładność do np 9 miejsca po przecinku?

Poniżej kod całego programu poniżej
(konieczne jest umieszczenie w tym samym katalogu pliku txt z podanymi granicami funkcji nazwa pliku: gadata.txt treść to granice podane w postaci (rozdzielone tabulatorem a nie spacją):
-2 2
-2 2

kod:
C/C++
/***************************************************************/
/* This is a simple genetic algorithm implementation where the */
/* evaluation function takes positive values only and the      */
/* fitness of an individual is the same as the value of the    */
/* objective function                                          */
/***************************************************************/

#include <stdio.h>
#include <stdlib.h> //srand
#include <math.h>
#include <string.h>

/* Change any of these parameters to match your needs */

#define POPSIZE 40               /* population size */
#define MAXGENS 200             /* max. number of generations */
#define NVARS 2                  /* no. of problem variables */
#define PXOVER 0.75               /* probability of crossover */
#define PMUTATION 0.15          /* probability of mutation */
#define TRUE 1
#define FALSE 0
#define ILOSC_PRZEBIEGOW 1

int generation; /* current generation no. */
int cur_best; /* best individual */
FILE * galog; /* an output file */

struct genotype /* genotype (GT), a member of the population */
{
    double gene[ NVARS ]; /* a string of variables */
    double fitness; /* GT's fitness */
    double upper[ NVARS ]; /* GT's variables upper bound */
    double lower[ NVARS ]; /* GT's variables lower bound */
    double rfitness; /* relative fitness */
    double cfitness; /* cumulative fitness */
};

struct genotype population[ POPSIZE + 1 ]; /* population */
struct genotype newpopulation[ POPSIZE + 1 ]; /* new population; */
/* replaces the */
/* old generation */

double wynik_najlepszy[ MAXGENS ][ ILOSC_PRZEBIEGOW ];
//double wynik_srednia[MAXGENS][ILOSC_PRZEBIEGOW];
//double wynik_sd[MAXGENS][ILOSC_PRZEBIEGOW];

double wynik_najlepszy_konc[ MAXGENS ];
double wynik_najlepszy_konc_sd[ MAXGENS ];
//double wynik_srednia_konc[MAXGENS];
//double wynik_sd_konc[MAXGENS];

/*
struct wynik
{
    double najlepsze_dopasow;
    double srednie_dopasow;
    double odchyl_stand;
}
struct genotype population_end_avg[MAXGENS];
*/

/* Declaration of procedures used by this genetic algorithm */

void initialize( void );
double randval( double, double );
void evaluate( void );
void keep_the_best( void );
void elitist( void );
void select_( void );
void crossover( void );
void Xover( int, int );
void swap( double *, double * );
void mutate( void );
void report( int );

/***************************************************************/
/* Initialization function: Initializes the values of genes    */
/* within the variables bounds. It also initializes (to zero)  */
/* all fitness values for each member of the population. It    */
/* reads upper and lower bounds of each variable from the      */
/* input file `gadata.txt'. It randomly generates values       */
/* between these bounds for each gene of each genotype in the  */
/* population. The format of the input file `gadata.txt' is    */
/* var1_lower_bound var1_upper bound                           */
/* var2_lower_bound var2_upper bound ...                       */
/***************************************************************/

void initialize( void )
{
    FILE * infile;
    int i, j;
    double lbound, ubound;
   
    if(( infile = fopen( "gadata.txt", "r" ) ) == NULL )
    {
        fprintf( galog, "\nCannot open input file!\n" );
        exit( 1 );
    }
   
    /* initialize variables within the bounds */
    //srand( time( NULL ) );  //punkt startowy dla mechanizmu generujcego liczny pseudolosowe
   
    for( i = 0; i < NVARS; i++ )
    {
        fscanf( infile, "%lf", & lbound );
        fscanf( infile, "%lf", & ubound );
       
        for( j = 0; j <= POPSIZE; j++ )
        {
            population[ j ].fitness = 0;
            population[ j ].rfitness = 0;
            population[ j ].cfitness = 0;
            population[ j ].lower[ i ] = lbound;
            population[ j ].upper[ i ] = ubound;
            population[ j ].gene[ i ] = randval( population[ j ].lower[ i ],
            population[ j ].upper[ i ] );
        }
    }
   
    fclose( infile );
}

/***********************************************************/
/* Random value generator: Generates a value within bounds */
/***********************************************************/

double randval( double low, double high )
{
    double val;
    val =(( double )( rand() % 10000000 ) / 1000000.0 ) *( high - low ) + low;
    printf( "%.9f\t", val );
   
    return( val );
}

/*************************************************************/
/* Evaluation function: This takes a user defined function.  */
/* Each time this is changed, the code has to be recompiled. */
/* The current function is:  x[1]^2-x[1]*x[2]+x[3]           */
/*************************************************************/

void evaluate( void )
{
    int mem;
    int i;
    double x[ NVARS + 1 ];
   
    for( mem = 0; mem < POPSIZE; mem++ )
    {
        for( i = 0; i < NVARS; i++ )
             x[ i + 1 ] = population[ mem ].gene[ i ];
       
        population[ mem ].fitness = 10000000 -( 1 +( x[ 1 ] + x[ 2 ] + 1 ) *( x[ 1 ] + x[ 2 ] + 1 ) *( 19 - 14 * x[ 1 ] + 3 * x[ 1 ] * x[ 1 ] - 14 * x[ 2 ] + 6 * x[ 1 ] * x[ 2 ] + 3 * x[ 2 ] * x[ 2 ] ) ) *( 30 +( 2 * x[ 1 ] - 3 * x[ 2 ] ) *( 2 * x[ 1 ] - 3 * x[ 2 ] ) *( 18 - 32 * x[ 1 ] + 12 * x[ 1 ] * x[ 1 ] + 48 * x[ 2 ] - 36 * x[ 1 ] * x[ 2 ] + 27 * x[ 2 ] * x[ 2 ] ) ); /*funkcja grzbietu wielblada szesciogarbnego*/
        //(x[1]*x[1]) - (x[1]*x[2]) + x[3]
    }
}

/***************************************************************/
/* Keep_the_best function: This function keeps track of the    */
/* best member of the population. Note that the last entry in  */
/* the array Population holds a copy of the best individual    */
/***************************************************************/
//trzyma najlepszy gen (od dwóch zmiennych) na ostatnim miejscu
void keep_the_best()
{
    int mem;
    int i;
    cur_best = 0; /* stores the index of the best individual */
   
    for( mem = 0; mem < POPSIZE; mem++ )
    {
        if( population[ mem ].fitness > population[ POPSIZE ].fitness )
        {
            cur_best = mem;
            population[ POPSIZE ].fitness = population[ mem ].fitness;
        }
    }
    /* once the best member in the population is found, copy the genes */
    for( i = 0; i < NVARS; i++ )
         population[ POPSIZE ].gene[ i ] = population[ cur_best ].gene[ i ];
   
}

/****************************************************************/
/* Elitist function: The best member of the previous generation */
/* is stored as the last in the array. If the best member of    */
/* the current generation is worse then the best member of the  */
/* previous generation, the latter one would replace the worst  */
/* member of the current population                             */
/****************************************************************/
//trzyma najlepszego dot¹d znalezionego osobnika w populacji (nawet jeœli w aktualnej populacji nie by³o lepszego ni¿ w poprzednich)
/* algorytm z ELITARYZMEM */
void elitist()
{
    int i;
    double best, worst; /* best and worst fitness values */
    int best_mem, worst_mem; /* indexes of the best and worst member */
   
    best = population[ 0 ].fitness;
    worst = population[ 0 ].fitness;
    for( i = 0; i < POPSIZE - 1; ++i )
    {
        if( population[ i ].fitness > population[ i + 1 ].fitness )
        {
            if( population[ i ].fitness >= best )
            {
                best = population[ i ].fitness;
                best_mem = i;
            }
            if( population[ i + 1 ].fitness <= worst )
            {
                worst = population[ i + 1 ].fitness;
                worst_mem = i + 1;
            }
        }
        else
        {
            if( population[ i ].fitness <= worst )
            {
                worst = population[ i ].fitness;
                worst_mem = i;
            }
            if( population[ i + 1 ].fitness >= best )
            {
                best = population[ i + 1 ].fitness;
                best_mem = i + 1;
            }
        }
    }
    /* if best individual from the new population is better than */
    /* the best individual from the previous population, then    */
    /* copy the best from the new population; else replace the   */
    /* worst individual from the current population with the     */
    /* best one from the previous generation                     */
   
   
    if( best >= population[ POPSIZE ].fitness )
    {
        for( i = 0; i < NVARS; i++ )
             population[ POPSIZE ].gene[ i ] = population[ best_mem ].gene[ i ];
       
        population[ POPSIZE ].fitness = population[ best_mem ].fitness;
    }
    else
    {
        for( i = 0; i < NVARS; i++ )
             population[ worst_mem ].gene[ i ] = population[ POPSIZE ].gene[ i ];
       
        population[ worst_mem ].fitness = population[ POPSIZE ].fitness;
    }
}
/**************************************************************/
/* Selection function: Standard proportional selection for    */
/* maximization problems incorporating elitist model - makes  */
/* sure that the best member survives                         */
/**************************************************************/

void select_( void )
{
    int mem, i, j, k;
    double sum = 0;
    double p;
   
    /* find total fitness of the population */
    for( mem = 0; mem < POPSIZE; mem++ )
    {
        sum += population[ mem ].fitness;
    }
   
    /* calculate relative fitness */
    for( mem = 0; mem < POPSIZE; mem++ )
    {
        population[ mem ].rfitness = population[ mem ].fitness / sum;
    }
    population[ 0 ].cfitness = population[ 0 ].rfitness;
   
    /* calculate cumulative fitness */
    for( mem = 1; mem < POPSIZE; mem++ )
    {
        population[ mem ].cfitness = population[ mem - 1 ].cfitness +
        population[ mem ].rfitness;
    }
   
    /* finally select survivors using cumulative fitness. */
   
    for( i = 0; i < POPSIZE; i++ )
    {
        //srand( time( NULL ) );  //punkt startowy dla mechanizmu generujcego liczny pseudolosowe
        p = rand() % 1000 / 1000.0;
        if( p < population[ 0 ].cfitness )
             newpopulation[ i ] = population[ 0 ];
        else
        {
            for( j = 0; j < POPSIZE; j++ )
            if( p >= population[ j ].cfitness &&
            p < population[ j + 1 ].cfitness )
                 newpopulation[ i ] = population[ j + 1 ];
           
        }
    }
    /* once a new population is created, copy it back */
   
    for( i = 0; i < POPSIZE; i++ )
         population[ i ] = newpopulation[ i ];
   
}

/***************************************************************/
/* Crossover selection: selects two parents that take part in  */
/* the crossover. Implements a single point crossover          */
/***************************************************************/

void crossover( void )
{
    int i, mem, one;
    int first = 0; /* count of the number of members chosen */
    double x;
   
    for( mem = 0; mem < POPSIZE; ++mem )
    {
        x = rand() % 10000 / 10000.0;
        if( x < PXOVER )
        {
            ++first;
            if( first % 2 == 0 )
                 Xover( one, mem );
            else
                 one = mem;
           
        }
    }
}
/**************************************************************/
/* Crossover: performs crossover of the two selected parents. */
/**************************************************************/

void Xover( int one, int two )
{
    int i;
    int point; /* crossover point */
   
    /* select crossover point */
    if( NVARS > 1 )
    {
        if( NVARS == 2 )
             point = 1;
        else
             point =( rand() %( NVARS - 1 ) ) + 1;
       
        for( i = 0; i < point; i++ )
             swap( & population[ one ].gene[ i ], & population[ two ].gene[ i ] );
       
    }
}

/*************************************************************/
/* Swap: A swap procedure that helps in swapping 2 variables */
/*************************************************************/

void swap( double * x, double * y )
{
    double temp;
   
    temp = * x;
    * x = * y;
    * y = temp;
   
}

/**************************************************************/
/* Mutation: Random uniform mutation. A variable selected for */
/* mutation is replaced by a random value between lower and   */
/* upper bounds of this variable                              */
/**************************************************************/

void mutate( void )
{
    int i, j;
    double lbound, hbound;
    double x;
   
    for( i = 0; i < POPSIZE; i++ )
    for( j = 0; j < NVARS; j++ )
    {
        x = rand() % 10000 / 10000.0;
        if( x < PMUTATION )
        {
            /* find the bounds on the variable to be mutated */
            lbound = population[ i ].lower[ j ];
            hbound = population[ i ].upper[ j ];
            population[ i ].gene[ j ] = randval( lbound, hbound );
        }
    }
}

/***************************************************************/
/* Report function: Reports progress of the simulation. Data   */
/* dumped into the  output file are separated by commas        */
/***************************************************************/

void report( int akt_przebieg )
{
    int i;
    double best_val = 0.0; /* best population fitness */
    double avg = 0.0; /* avg population fitness */
    double stddev = 0.0; /* std. deviation of population fitness */
    double sum_square = 0.0; /* sum of square for std. calc */
    double square_sum = 0.0; /* square of sum for std. calc */
    double sum = 0.0; /* total population fitness */
   
    sum = 0.0;
    sum_square = 0.0;
   
    for( i = 0; i < POPSIZE; i++ )
    {
        sum += population[ i ].fitness;
        sum_square += population[ i ].fitness * population[ i ].fitness;
    }
   
    avg = sum /( double ) POPSIZE;
    square_sum = avg * avg * POPSIZE;
    stddev = sqrt(( sum_square - square_sum ) /( POPSIZE - 1 ) );
    best_val = population[ POPSIZE ].fitness;
   
    //fprintf(galog, "\n%5d\t%6.4f\t%6.4f\t%6.4f", generation, best_val, avg, stddev);
   
    wynik_najlepszy[ generation - 1 ][ akt_przebieg - 1 ] = best_val;
    //wynik_srednia[generation][akt_przebieg] = avg;
    //wynik_sd[generation][akt_przebieg] = stddev;
}





/***************************************************************/
/* Report function: Reports progress of the simulation. Data   */
/* dumped into the  output file are separated by commas        */
/***************************************************************/

void raport_end( void )
{
    /*
    wynik_najlepszy[generation] = best_val,
    wynik_srednia[generation] = avg;
    wynik_sd[generation] = stddev;
    */
   
    int generacja, j;
    double suma = 0.0, sum_square = 0.0, square_sum = 0.0, avg = 0.0, stddev = 0.0;
   
    fprintf( galog, "\n\n\n\n ***** OSTATECZNIE *****\n" );
   
    for( generacja = 0; generacja < MAXGENS; generacja++ ) {
        for( j = 0; j < ILOSC_PRZEBIEGOW; j++ ) {
            suma += wynik_najlepszy[ generacja ][ j ];
            sum_square += wynik_najlepszy[ generacja ][ j ] * wynik_najlepszy[ generacja ][ j ];
            //srednia += wynik_srednia[i][j];
        }
        wynik_najlepszy_konc[ generacja ] = suma /( double ) ILOSC_PRZEBIEGOW;
        avg = wynik_najlepszy_konc[ generacja ];
        //printf("avg: %6.4f\t",avg);
        square_sum = avg * avg * ILOSC_PRZEBIEGOW;
        //printf("sum_square: %6.4f\t",sum_square);
        //printf("square_sum: %6.4f\t",square_sum);
        stddev = sqrt(( sum_square - square_sum ) /( POPSIZE - 1 ) );
        //printf("stddev: %6.4f\n",stddev);
        wynik_najlepszy_konc_sd[ generacja ] = stddev;
        suma = 0.0;
        sum_square = 0.0;
        //wynik_srednia[generacja] = srednia/ILOSC_PRZEBIEGOW;
       
        fprintf( galog, "\n%5d\t%.9f\t%.9f\t", generacja + 1,
        10000000 - wynik_najlepszy_konc[ generacja ], wynik_najlepszy_konc_sd[ generacja ] );
       
    }
   
}


/**************************************************************/
/* Main function: Each generation involves selecting the best */
/* members, performing crossover & mutation and then          */
/* evaluating the resulting population, until the terminating */
/* condition is satisfied                                     */
/**************************************************************/

void main( void )
{
    int i, j;
    srand( time( NULL ) ); //punkt startowy dla mechanizmu generujcego liczny pseudolosowe
   
   
    /*const char* jj="_1";
        char tytul[10000] = "galog";
        const char* rozszerzenie = ".txt";
        char* nazwa;*/
   
   
    if(( galog = fopen( "galog_.txt", "w" ) ) == NULL )
    {
        exit( 1 );
    }
    for( j = 1; j <= ILOSC_PRZEBIEGOW; j++ ) {
       
        /*
                //jj = (const char*)j;                   printf("%s", jj);
                printf("%d",j);
                printf("%s",(char*)j);
                strcat(tytul, (const char*)j); printf("la");
                strcat(tytul, rozszerzenie);
                puts(tytul);
                */
       
        /*if ((galog = fopen("galog_.txt","w"))==NULL)
                      {
                      exit(1);
                      }*/
        generation = 0;
       
        //fprintf(galog, "\n************************************************\n************************************************\n\n ");
        /*fprintf(galog, "\n Test no. ");
                fprintf(galog, "%d \n\n", j);
                fprintf(galog, "\n generation  best  average  standard \n");
                fprintf(galog, " number      value fitness  deviation \n");
        */
        initialize();
        evaluate();
        keep_the_best();
        while( generation < MAXGENS )
        {
            generation++;
            select_();
            crossover();
            mutate();
            report( j );
            evaluate();
            elitist();
            //wynik[generation]= best_val, avg, stddev
        }
        //fprintf(galog,"\n\n Simulation completed\n");
        //fprintf(galog,"\n Best member: \n");
        printf( "\n Best member: \n" );
       
        for( i = 0; i < NVARS; i++ )
        {
            fprintf( galog, "\n var(%d) = \t%3.15f", i, population[ POPSIZE ].gene[ i ] );
           
            printf( "\n var(%d) = \t%.15f", i, population[ POPSIZE ].gene[ i ] );
        }
       
        //fprintf(galog,"\n\n Best fitness = \t%3.4f",population[POPSIZE].fitness);
        //fprintf(galog,"\n\n Minimum value = \t%3.4f",10000000-population[POPSIZE].fitness);
        //fclose(galog);
        printf( "\nSuccess\n" );
        //printf("%d",sizeof(double));
        /*double val;
                double high = 2.0;
                double low = -2.0;
                int i;
                for ( i=0; i< 100 ;i++) {
                 val = ((double)(rand()%100000)/100000.0)*(high - low)+low;
                 printf(" tera %.15f teraz koniec",val);
                 }*/
       
        printf( "\n\n Best fitness = \t%.15f\n\n", population[ POPSIZE ].fitness );
        printf( "\n\n Minimum value = \t%.15f\n", 10000000 - population[ POPSIZE ].fitness );
    } //for
    raport_end();
    fclose( galog );
} //main
/***************************************************************/
P-162707
carlosmay
» 2017-06-20 00:06:18
P-162708
michal11
» 2017-06-20 00:17:08
P-162709
« 1 »
  Strona 1 z 1