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: 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:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h>
#define POPSIZE 40 #define MAXGENS 200 #define NVARS 2 #define PXOVER 0.75 #define PMUTATION 0.15 #define TRUE 1 #define FALSE 0 #define ILOSC_PRZEBIEGOW 1
int generation; int cur_best; FILE * galog;
struct genotype { double gene[ NVARS ]; double fitness; double upper[ NVARS ]; double lower[ NVARS ]; double rfitness; double cfitness; };
struct genotype population[ POPSIZE + 1 ]; struct genotype newpopulation[ POPSIZE + 1 ];
double wynik_najlepszy[ MAXGENS ][ ILOSC_PRZEBIEGOW ];
double wynik_najlepszy_konc[ MAXGENS ]; double wynik_najlepszy_konc_sd[ MAXGENS ];
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 );
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 ); } 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 ); }
double randval( double low, double high ) { double val; val =(( double )( rand() % 10000000 ) / 1000000.0 ) *( high - low ) + low; printf( "%.9f\t", val ); return( val ); }
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 ] ) ); } }
void keep_the_best() { int mem; int i; cur_best = 0; for( mem = 0; mem < POPSIZE; mem++ ) { if( population[ mem ].fitness > population[ POPSIZE ].fitness ) { cur_best = mem; population[ POPSIZE ].fitness = population[ mem ].fitness; } } for( i = 0; i < NVARS; i++ ) population[ POPSIZE ].gene[ i ] = population[ cur_best ].gene[ i ]; }
void elitist() { int i; double best, worst; int best_mem, worst_mem; 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 >= 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; } }
void select_( void ) { int mem, i, j, k; double sum = 0; double p; for( mem = 0; mem < POPSIZE; mem++ ) { sum += population[ mem ].fitness; } for( mem = 0; mem < POPSIZE; mem++ ) { population[ mem ].rfitness = population[ mem ].fitness / sum; } population[ 0 ].cfitness = population[ 0 ].rfitness; for( mem = 1; mem < POPSIZE; mem++ ) { population[ mem ].cfitness = population[ mem - 1 ].cfitness + population[ mem ].rfitness; } for( i = 0; i < POPSIZE; i++ ) { 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 ]; } } for( i = 0; i < POPSIZE; i++ ) population[ i ] = newpopulation[ i ]; }
void crossover( void ) { int i, mem, one; int first = 0; 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; } } }
void Xover( int one, int two ) { int i; int 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 ] ); } }
void swap( double * x, double * y ) { double temp; temp = * x; * x = * y; * y = temp; }
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 ) { lbound = population[ i ].lower[ j ]; hbound = population[ i ].upper[ j ]; population[ i ].gene[ j ] = randval( lbound, hbound ); } } }
void report( int akt_przebieg ) { int i; double best_val = 0.0; double avg = 0.0; double stddev = 0.0; double sum_square = 0.0; double square_sum = 0.0; double sum = 0.0; 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; wynik_najlepszy[ generation - 1 ][ akt_przebieg - 1 ] = best_val; }
void raport_end( void ) { 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 ]; } wynik_najlepszy_konc[ generacja ] = suma /( double ) ILOSC_PRZEBIEGOW; avg = wynik_najlepszy_konc[ generacja ]; square_sum = avg * avg * ILOSC_PRZEBIEGOW; stddev = sqrt(( sum_square - square_sum ) /( POPSIZE - 1 ) ); wynik_najlepszy_konc_sd[ generacja ] = stddev; suma = 0.0; sum_square = 0.0; fprintf( galog, "\n%5d\t%.9f\t%.9f\t", generacja + 1, 10000000 - wynik_najlepszy_konc[ generacja ], wynik_najlepszy_konc_sd[ generacja ] ); } }
void main( void ) { int i, j; srand( time( NULL ) ); if(( galog = fopen( "galog_.txt", "w" ) ) == NULL ) { exit( 1 ); } for( j = 1; j <= ILOSC_PRZEBIEGOW; j++ ) { generation = 0; initialize(); evaluate(); keep_the_best(); while( generation < MAXGENS ) { generation++; select_(); crossover(); mutate(); report( j ); evaluate(); elitist(); } 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 ] ); } printf( "\nSuccess\n" ); printf( "\n\n Best fitness = \t%.15f\n\n", population[ POPSIZE ].fitness ); printf( "\n\n Minimum value = \t%.15f\n", 10000000 - population[ POPSIZE ].fitness ); } raport_end(); fclose( galog ); }
|