Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cstdlib>
- #include <cmath>
- #define POL_VARS (4) // ilość zmiennych wielomianu
- #define POL_1 (3) // ilość elementów pierwszego stopnia
- #define POL_2 (3) // ilość elementów drugiego stopnia
- #define POL_3 (3) // ilość elementów trzeciego stopnia
- #define POL_RNG (200) // zakres wartości współczynników wielomianu
- #define DATA_RNG (6.0) // zakres zmiennych wejściowych wielomianu
- #define DATA_CNT ((POL_1+POL_2+POL_3)*2) // ilość danych na których będą aproksymowane losowe wielomiany
- #define SYM_CNT (5) // ilość symulacji
- #define SYM_ALL_GAMES (2000000000) // ilość turniejów
- #define SYM_CNT_PROG (10) // ilość programów w turnieju
- #define SYM_PAIR_GAMES (2) // ilość gier dla każdej pary
- #define SYM_TOURNS (SYM_ALL_GAMES/(SYM_CNT_PROG*(SYM_CNT_PROG-1)/2*SYM_PAIR_GAMES)) // ilość turniejów
- #define SYM_RAND1 (4.00) // zaburzenia stałe
- #define SYM_RAND2 (0.00) // zaburzenia procentowe
- #define SYM_STEP_START (0.0001) // krok uczący
- #define SYM_STEP_END (0.0001) // krok uczący
- #define CHAOS (0.10) // chaos dodawany do parametrów przed rozgrywką
- struct VarPoly {
- int pol1[POL_1>0?POL_1:1];
- int pol2[POL_2>0?POL_2:1];
- int pol3[POL_3>0?POL_3:1];
- };
- // wielomian
- struct Pol {
- double pol1[POL_1>0?POL_1:1];
- double pol2[POL_2>0?POL_2:1];
- double pol3[POL_3>0?POL_3:1];
- };
- struct Data {
- double x[POL_VARS]; // wejście
- double y; // wyjście
- };
- double frand() {
- double r = rand() % 1024;
- r *= 1024;
- r += rand() % 1024;
- return r / 1024.0 / 1024.0;
- }
- void randVar( VarPoly &var_pol ) {
- for( int i=0 ; i<POL_1 ; i++ ) {
- var_pol.pol1[i] = rand() % POL_VARS;
- for( int j=0 ; j<i ; j++ ) {
- if( var_pol.pol1[j] == var_pol.pol1[i] ) {
- i--;
- break;
- }
- }
- }
- for( int i=0 ; i<POL_2 ; i++ ) {
- var_pol.pol2[i] = rand() % POL_VARS;
- var_pol.pol2[i] = rand() % POL_VARS;
- for( int j=0 ; j<i ; j++ ) {
- if( var_pol.pol2[j] == var_pol.pol2[i] && var_pol.pol2[j] == var_pol.pol2[i] ) {
- i--;
- break;
- }
- }
- }
- for( int i=0 ; i<POL_3 ; i++ ) {
- var_pol.pol3[i] = rand() % POL_VARS;
- var_pol.pol3[i] = rand() % POL_VARS;
- var_pol.pol3[i] = rand() % POL_VARS;
- for( int j=0 ; j<i ; j++ ) {
- if( var_pol.pol3[j] == var_pol.pol3[i] && var_pol.pol3[j] == var_pol.pol3[i] && var_pol.pol3[j] == var_pol.pol3[i] ) {
- i--;
- break;
- }
- }
- }
- }
- // tworzymy zupełnie losowy wielomian
- void randPol( Pol &pol ) {
- for( int i=0 ; i<POL_1 ; i++ ) pol.pol1[i] = frand() * POL_RNG * 2 - POL_RNG;
- for( int i=0 ; i<POL_2 ; i++ ) pol.pol2[i] = frand() * POL_RNG * 2 - POL_RNG;
- for( int i=0 ; i<POL_3 ; i++ ) pol.pol3[i] = frand() * POL_RNG * 2 - POL_RNG;
- }
- // tworzymy losowy wielomian w pobliżu wielomianu bazowego
- void randomNear( Pol &pol , const Pol &base ) {
- pol = base;
- for( int i=0 ; i<POL_1 ; i++ ) pol.pol1[i] += fabs( pol.pol1[i] ) * ( frand() * SYM_RAND2 * 2 - SYM_RAND2 ) + frand() * SYM_RAND1 * 2 - SYM_RAND1;
- for( int i=0 ; i<POL_2 ; i++ ) pol.pol2[i] += fabs( pol.pol2[i] ) * ( frand() * SYM_RAND2 * 2 - SYM_RAND2 ) + frand() * SYM_RAND1 * 2 - SYM_RAND1;
- for( int i=0 ; i<POL_3 ; i++ ) pol.pol3[i] += fabs( pol.pol3[i] ) * ( frand() * SYM_RAND2 * 2 - SYM_RAND2 ) + frand() * SYM_RAND1 * 2 - SYM_RAND1;
- }
- // obliczamy wartość wielomianu
- double computePol( const double x[POL_VARS] , const VarPoly &var , const Pol &pol ) {
- double y = 0;
- for( int i=0 ; i<POL_1 ; i++ ) y += pol.pol1[i] * x[ var.pol1[i] ];
- for( int i=0 ; i<POL_2 ; i++ ) y += pol.pol2[i] * x[ var.pol2[i] ] * x[ var.pol2[i] ];
- for( int i=0 ; i<POL_3 ; i++ ) y += pol.pol3[i] * x[ var.pol3[i] ] * x[ var.pol3[i] ] * x[ var.pol3[i] ];
- return y;
- }
- // obliczamy błąd wielomianu
- double errorPol( const Data data[DATA_CNT] , const VarPoly &var , const Pol &pol ) {
- double er = 0;
- for( int i=0 ; i<DATA_CNT ; i++ ) {
- const double tmp = computePol( data[i].x , var , pol ) - data[i].y;
- er += tmp * tmp;
- }
- return sqrt( er / DATA_CNT );
- }
- // tworzymy losowe dane, tak aby były zgodne z wielomianem. w
- // ten sposób uzyskujemy wielomian idealnie zaproksymowany.
- void makeData( Data data[DATA_CNT] , const VarPoly &var , const Pol &pol ) {
- for( int i=0 ; i<DATA_CNT ; i++ ) {
- for( int j=0 ; j<POL_VARS ; j++ )
- data[i].x[j] = frand() * DATA_RNG * 2 - DATA_RNG;
- data[i].y = computePol( data[i].x , var , pol );
- }
- }
- static unsigned int cnt_games = 0;
- // wyłaniamy wielomian zwycięski
- int tournament( const Data data[DATA_CNT] , const VarPoly &var , const Pol pol[SYM_CNT_PROG] ) {
- int res[SYM_CNT_PROG];
- for( int i=0 ; i<SYM_CNT_PROG ; i++ )
- res[i] = 0;
- for( int i=0 ; i<SYM_CNT_PROG-1 ; i++ ) {
- for( int j=i+1 ; j<SYM_CNT_PROG ; j++ ) {
- for( int k=0 ; k<SYM_PAIR_GAMES ; k++ ) {
- Pol pol1 = pol[i];
- Pol pol2 = pol[j];
- for( int l=0 ; l<POL_1 ; l++ ) { pol1.pol1[l] += pol1.pol1[l] * (frand() * CHAOS * 2 - CHAOS); pol2.pol1[l] += pol2.pol1[l] * (frand() * CHAOS * 2 - CHAOS); }
- for( int l=0 ; l<POL_2 ; l++ ) { pol1.pol2[l] += pol1.pol2[l] * (frand() * CHAOS * 2 - CHAOS); pol2.pol2[l] += pol2.pol2[l] * (frand() * CHAOS * 2 - CHAOS); }
- for( int l=0 ; l<POL_3 ; l++ ) { pol1.pol3[l] += pol1.pol3[l] * (frand() * CHAOS * 2 - CHAOS); pol2.pol3[l] += pol2.pol3[l] * (frand() * CHAOS * 2 - CHAOS); }
- const double val1 = errorPol( data , var , pol1 );
- const double val2 = errorPol( data , var , pol2 );
- if( val1 < val2 ) res[i] += 2;
- else if( val2 < val1 ) res[j] += 2;
- else { res[i] += 1; res[j] += 1; }
- cnt_games ++ ;
- }}}
- int max = 0;
- for( int i=1 ; i<SYM_CNT_PROG ; i++ )
- if( res[max] < res[i] )
- max = i;
- return max;
- }
- // uczymy przez przesunięcie wielomianu bazowego do zwycięskiego
- void learnBase( Pol &base , const Pol &win , const double step ) {
- for( int i=0 ; i<POL_1 ; i++ ) base.pol1[i] += ( win.pol1[i] - base.pol1[i] ) * step;
- for( int i=0 ; i<POL_2 ; i++ ) base.pol2[i] += ( win.pol2[i] - base.pol2[i] ) * step;
- for( int i=0 ; i<POL_3 ; i++ ) base.pol3[i] += ( win.pol3[i] - base.pol3[i] ) * step;
- }
- // odległość pomiędzy dwoma rozwiązaniami
- double distPol( const Pol &pol1 , const Pol &pol2 ) {
- double dist = 0;
- for( int i=0 ; i<POL_1 ; i++ ) dist += ( pol1.pol1[i] - pol2.pol1[i] ) * ( pol1.pol1[i] - pol2.pol1[i] );
- for( int i=0 ; i<POL_2 ; i++ ) dist += ( pol1.pol2[i] - pol2.pol2[i] ) * ( pol1.pol2[i] - pol2.pol2[i] );
- for( int i=0 ; i<POL_3 ; i++ ) dist += ( pol1.pol3[i] - pol2.pol3[i] ) * ( pol1.pol3[i] - pol2.pol3[i] );
- return sqrt( dist / (POL_1+POL_2+POL_3) );
- }
- double learnSym( const Data data[DATA_CNT] , const VarPoly &var , Pol &base , const Pol &best ) {
- printf("start %10.4lf %10.4lf %10.4lf\n", errorPol(data,var,base) , distPol(base,best) , errorPol(data,var,best) );
- fflush(stdout);
- double step = SYM_STEP_START;
- const double fade = pow( SYM_STEP_END/SYM_STEP_START , 1.0 / ( SYM_TOURNS - 1.0 ) );
- for( int i=0 ; i < SYM_TOURNS ; i++ ) {
- Pol progs[SYM_CNT_PROG];
- for( int j=0 ; j<SYM_CNT_PROG ; j++ )
- randomNear( progs[j] , base );
- const int win = tournament( data , var , progs );
- learnBase( base , progs[win] , step );
- if( i%10000 == 0) {
- printf("%.2lf %lf %lf\n", cnt_games/1000000.0 , errorPol(data,var,base) , distPol(base,best) );
- fflush(stdout);
- }
- step *= fade;
- }
- printf("end %10.4lf %10.4lf %10.4lf\n" , errorPol(data,var,base) , distPol(base,best) , step/fade );
- fflush(stdout);
- return errorPol(data,var,base);
- }
- unsigned long long seeds[] = {0x4FF12B4EEC03E700ULL, 0x57E6398A9A8B2211ULL, 0xB4615E9685F2E8C3ULL, 0x022F867DF087C9E6ULL, 0xA03563B9C243B8EFULL, 0x5FC7323AF7033998ULL, 0x30823328BAC9CE98ULL, 0x573D9C22D4502AAEULL, 0xDED29242FE519A8BULL, 0x19AE2C4DEF0BC015ULL, 0x1C1CC71A3EB3A4A1ULL, 0xEEC970FC319CFC1FULL, 0x528D055C3D49DA99ULL, 0x1741B598B3F6109BULL, 0x28D335B91AEA7F39ULL, 0xDEDDAD64D3D95FF4ULL, 0xAA3C089F12C25F19ULL, 0xC539DC621B4D0606ULL, 0x9F2AC28AC4737A16ULL, 0xB72DAB1C2F4F590CULL, 0xB271B5F30AD8962EULL, 0xE5B30FCF64399ECEULL, 0x748A6AF8D0AE84BAULL, 0xC4AB1BC380199A5AULL, 0x8EDD48734A9EAE33ULL, 0xC36CF389A2E5192BULL, 0x42BA73766378DF33ULL, 0x469662938753D3DEULL, 0xE970C2AF0F7927C1ULL, 0xBD7A23F4323E674EULL, 0xD829F9FC6BB983C9ULL, 0xBDEA784DB2D7E5B4ULL, 0xD4C4B06BAE93256BULL, 0xEB544E6E115E722CULL, 0xEA47168DADE23E4BULL, 0xC8BB649C22785FB8ULL, 0xBF53BC7FE55202E0ULL, 0xDFC89D57F776F9BBULL, 0x816A616E35380CC6ULL, 0x632E6BAAA6E915DDULL, 0x78ACA5D7424B28A9ULL, 0x80CF3CA43095C9D5ULL, 0x9BAB2DEFB47A99FCULL, 0xEC65A533A95BC5B8ULL, 0x340F702E2FFAC876ULL, 0x88EE4367DDC6C0C1ULL, 0x6F1A7414008F85C6ULL, 0xCAF21613FCB05677ULL, 0x5DF1C1DD328C861BULL, 0xBFC94418AE2CBBF2ULL, 0x2C7D71B3A5AACF75ULL, 0x44FEDB5C8DAC34D8ULL, 0xDD6E940D0EC37EFCULL, 0x4A811353B367B2C7ULL, 0x486CCADEDA12BE85ULL, 0x01A1157CC0E7773FULL, 0xECF76F3947EF30A7ULL, 0xA9CB41DC150433B5ULL, 0xC9D1962CF2F0CB79ULL, 0x6C97F08D41EE92BAULL, 0xFBEAE85B9913C397ULL, 0xC12C6A8813EB33B1ULL, 0xBF3618CBAB212896ULL, 0xC5251C97FE1A8D1AULL};
- int main(int argc, char *argv[]) {
- double sum_error = 0;
- for( int i=0 ; i<SYM_CNT ; i++ ) {
- Data data[DATA_CNT];
- VarPoly var;
- Pol best,base;
- if( i >= sizeof(seeds)/sizeof(seeds[0]) )
- abort();
- srand( seeds[i] );
- randPol( best );
- randPol( base );
- randVar( var );
- makeData( data ,var, best );
- sum_error += learnSym( data , var , base , best );
- }
- printf("%9d %2d %6.4lf %6.4lf %6.4lf %6.4lf %10.4lf\n" , SYM_ALL_GAMES , SYM_CNT_PROG , SYM_RAND1 , SYM_RAND2 , SYM_STEP_START , SYM_STEP_END , sum_error/SYM_CNT );
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment