Verifikasi numerik hipotesis abc (ya, yang itu)

Hai, Habr.

Sudah ada beberapa artikel tentang hipotesis abc di Geektimes Habr (misalnya, pada 2013 dan 2018 ). Cerita itu sendiri tentang sebuah teorema yang pada awalnya tidak dapat dibuktikan selama bertahun-tahun, dan kemudian tidak dapat diverifikasi untuk jumlah tahun yang sama, tentu layak setidaknya film layar lebar. Tetapi dalam bayang-bayang kisah yang indah ini, teorema itu sendiri dianggap terlalu dangkal, meskipun tidak kalah menarik. Setidaknya dengan fakta bahwa hipotesis abc adalah salah satu dari beberapa masalah sains modern yang tidak terpecahkan, pernyataan masalah yang bahkan dapat dipahami oleh siswa kelas lima. Jika hipotesis ini benar, maka dengan mudah mengikuti dari bukti teorema penting lainnya, misalnya, bukti teorema Fermat .

Tanpa mengklaim kemenangan Motizuki, saya juga memutuskan untuk mencoba dan memutuskan untuk memeriksa dengan komputer berapa banyak persamaan yang dijanjikan dalam hipotesis terpenuhi. Sebenarnya, mengapa tidak - prosesor modern tidak hanya untuk bermain game - mengapa tidak menggunakan komputer untuk tujuan utama (menghitung) ...

Siapa peduli apa yang terjadi, tolong, di bawah kucing.

Pernyataan masalah


Mari kita mulai dari awal. Tentang apa teorema itu? Seperti yang dikatakan Wikipedia (kata-kata dalam versi bahasa Inggris sedikit lebih jelas), untuk saling sederhana (tidak memiliki pembagi umum) angka a, b dan c sedemikian sehingga a + b = c, untuk setiap Ξ΅> 0 ada jumlah triples a + b yang terbatas = c, sedemikian rupa sehingga:



Fungsi rad disebut radikal , dan menunjukkan produk dari faktor prima suatu bilangan. Misalnya, rad (16) = rad (2 * 2 * 2 * 2) = 2, rad (17) = 17 (17 adalah bilangan prima), rad (18) = rad (2 * 3 * 3) = 2 * 3 = 6, rad (1.000.000) = rad (2 ^ 6 β‹… 5 ^ 6) = 2 * 5 = 10.

Sebenarnya, inti dari teorema ini adalah bahwa jumlah tiga kali lipat semacam itu cukup kecil. Sebagai contoh, jika kita mengambil secara acak Ξ΅ = 0,2 dan persamaan 100 + 27 = 127: rad (100) = rad (2 * 2 * 5 * 5) = 10, rad (27) = rad (3 * 3 * 3) = 3, rad (127) = 127, rad (a * b * c) = rad (a) * rad (b) * rad (c) = 3810, 3810 ^ 1.2 jelas lebih besar dari 127, ketidaksetaraan tidak berlaku. Tetapi ada pengecualian, misalnya, untuk kesetaraan 49 + 576 = 625, kondisi teorema terpenuhi (mereka yang ingin dapat memeriksa sendiri).

Momen kunci berikutnya bagi kita adalah sejumlah persamaan ini, menurut teorema. Yaitu ini berarti Anda bisa mencoba memilah semuanya di komputer. Sebagai hasilnya, ini memberi kita Hadiah Nobel tugas pemrograman yang cukup menarik.

Jadi mari kita mulai.

Kode sumber


Versi pertama ditulis dalam Python, dan meskipun bahasa ini terlalu lambat untuk perhitungan seperti itu, menulis kode di atasnya mudah dan sederhana, yang nyaman untuk pembuatan prototipe.

Mendapatkan radikal : kami menguraikan angka menjadi faktor prima, lalu menghapus pengulangan, mengubah array menjadi satu set. Kemudian dapatkan produk dari semua elemen.

def prime_factors(n): factors = [] # Print the number of two's that divide n while n % 2 == 0: factors.append(int(2)) n = n / 2 # n must be odd at this point so a skip of 2 ( i = i + 2) can be used for i in range(3, int(math.sqrt(n)) + 1, 2): # while i divides n , print i ad divide n while n % i == 0: factors.append(int(i)) n = n / i # Condition if n is a prime number greater than 2 if n > 2: factors.append(int(n)) return set(factors) def rad(n): result = 1 for num in prime_factors(n): result *= num return result 

Bilangan prima yang saling menguntungkan : faktor-faktor angka, dan cukup periksa persimpangan set.

 def not_mutual_primes(a,b,c): fa, fb, fc = prime_factors(a), prime_factors(b), prime_factors(c) return len(fa.intersection(fb)) == 0 and len(fa.intersection(fc)) == 0 and len(fb.intersection(fc)) == 0 

Periksa : kami menggunakan fungsi yang sudah dibuat, semuanya sederhana di sini.

 def check(a,b,c): S = 1.2 # Eps=0.2 if c > (rad(a)*rad(b)*rad(c))**S and not_mutual_primes(a, b, c): print("{} + {} = {} - PASSED".format(a, b, c)) else: print("{} + {} = {} - FAILED".format(a, b, c)) check(10, 17, 27) check(49, 576, 625) 

Mereka yang ingin dapat bereksperimen secara mandiri dengan menyalin kode di atas ke editor bahasa Python online. Tentu saja, kode berjalan seperti yang diharapkan, dan menghitung semua tiga kali lipat untuk setidaknya satu juta akan terlalu lama. Di bawah spoiler ada versi yang dioptimalkan, disarankan untuk menggunakannya.

Versi terakhir ditulis ulang dalam C ++ menggunakan multithreading dan beberapa optimasi (bekerja di C dengan set berpotongan akan terlalu hardcore, meskipun mungkin lebih cepat). Kode sumber berada di bawah spoiler, dapat dikompilasi dalam kompiler g ++ gratis, kode tersebut bekerja di bawah Windows, OSX dan bahkan pada Raspberry Pi.

Kode C ++
 // To compile: g++ abc.cpp -O3 -fopenmp -oabc #include <string.h> #include <math.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <vector> #include <set> #include <map> #include <algorithm> #include <time.h> typedef unsigned long int valType; typedef std::vector<valType> valList; typedef std::set<valType> valSet; typedef valList::iterator valListIterator; std::vector<valList> valFactors; std::vector<double> valRads; valList factors(valType n) { valList results; valType z = 2; while (z * z <= n) { if (n % z == 0) { results.push_back(z); n /= z; } else { z++; } } if (n > 1) { results.push_back(n); } return results; } valList unique_factors(valType n) { valList results = factors(n); valSet vs(results.begin(), results.end()); valList unique(vs.begin(), vs.end()); std::sort(unique.begin(), unique.end()); return unique; } double rad(valType n) { valList f = valFactors[n]; double result = 1; for (valListIterator it=f.begin(); it<f.end(); it++) { result *= *it; } return result; } bool not_mutual_primes(valType a, valType b, valType c) { valList res1 = valFactors[a], res2 = valFactors[b], res3; // = valFactors[c]; valList c12, c13, c23; set_intersection(res1.begin(),res1.end(), res2.begin(),res2.end(), back_inserter(c12)); if (c12.size() != 0) return false; res3 = valFactors[c]; set_intersection(res1.begin(),res1.end(), res3.begin(),res3.end(), back_inserter(c13)); if (c13.size() != 0) return false; set_intersection(res2.begin(),res2.end(), res3.begin(),res3.end(), back_inserter(c23)); return c23.size() == 0; } int main() { time_t start_t, end_t; time(&start_t); int cnt=0; double S = 1.2; valType N_MAX = 10000000; printf("Getting prime factors...\n"); valFactors.resize(2*N_MAX+2); valRads.resize(2*N_MAX+2); for(valType val=1; val<=2*N_MAX+1; val++) { valFactors[val] = unique_factors(val); valRads[val] = rad(val); } time(&end_t); printf("Done, T = %.2fs\n", difftime(end_t, start_t)); printf("Calculating...\n"); #pragma omp parallel for reduction(+:cnt) for(int a=1; a<=N_MAX; a++) { for(int b=a; b<=N_MAX; b++) { int c = a+b; if (c > pow(valRads[a]*valRads[b]*valRads[c], S) && not_mutual_primes(a,b,c)) { printf("%d + %d = %d\n", a,b,c); cnt += 1; } } } printf("Done, cnt=%d\n", cnt); time(&end_t); float diff_t = difftime(end_t, start_t); printf("N=%lld, T = %.2fs\n", N_MAX, diff_t); } 


Bagi mereka yang terlalu malas untuk menginstal kompiler C ++, disediakan versi Python yang sedikit dioptimalkan, yang dapat dijalankan di editor online mana pun (saya menggunakan https://repl.it/languages/python ).

Versi python
 from __future__ import print_function import math import time import multiprocessing prime_factors_list = [] rad_list = [] def prime_factors(n): factors = [] # Print the number of two's that divide n while n % 2 == 0: factors.append(int(2)) n = n / 2 # n must be odd at this point so a skip of 2 ( i = i + 2) can be used for i in range(3, int(math.sqrt(n)) + 1, 2): # while i divides n , print i ad divide n while n % i == 0: factors.append(int(i)) n = n / i # Condition if n is a prime number greater than 2 if n > 2: factors.append(int(n)) return factors def rad(n): result = 1 for num in prime_factors_list[n]: result *= num return result def not_mutual_primes(a,b,c): fa, fb, fc = prime_factors_list[a], prime_factors_list[b], prime_factors_list[c] return len(fa.intersection(fb)) == 0 and len(fa.intersection(fc)) == 0 and len(fb.intersection(fc)) == 0 def calculate(N): S = 1.2 cnt = 0 for a in range(1, N): for b in range(a, N): c = a+b if c > (rad_list[a]*rad_list[b]*rad_list[c])**S and not_mutual_primes(a, b, c): print("{} + {} = {}".format(a, b, c)) cnt += 1 print("N: {}, CNT: {}".format(N, cnt)) return cnt if __name__ == '__main__': t1 = time.time() NMAX = 100000 prime_factors_list = [0]*(2*NMAX+2) rad_list = [0]*(2*NMAX+2) for p in range(1, 2*NMAX+2): prime_factors_list[p] = set(prime_factors(p)) rad_list[p] = rad(p) calculate(NMAX) print("Done", time.time() - t1) 


Hasil


Tiga kali lipat a, b, c benar-benar sangat sedikit.

Beberapa hasil diberikan di bawah ini:
N = 10 : 1 β€œtiga”, lead time <0,001c
1 + 8 = 9

N = 100 : 2 β€œtiga kali lipat”, runtime <0,001c
1 + 8 = 9
1 + 80 = 81

N = 1000 : 8 "tiga kali lipat", runtime <0,01c
1 + 8 = 9
1 + 80 = 81
1 + 242 = 243
1 + 288 = 289
1 + 512 = 513
3 + 125 = 128
13 + 243 = 256
49 + 576 = 625

N = 10.000 : 23 "tiga kali lipat", runtime 2s

Tiga A, B, C hingga 10.000
1 + 8 = 9
1 + 80 = 81
1 + 242 = 243
1 + 288 = 289
1 + 512 = 513
1 + 2400 = 2401
1 + 4374 = 4375
1 + 5831 = 5832
1 + 6560 = 6561
1 + 6655 = 6656
1 + 6859 = 6860
3 + 125 = 128
5 + 1024 = 1029
10 + 2187 = 2197
11 + 3125 = 3136
13 + 243 = 256
49 + 576 = 625
1331 + 9604 = 10935
81 + 1250 = 1331
125 + 2187 = 2312
243 + 1805 = 2048
289 + 6272 = 6561
625 + 2048 = 2673

N = 100000 : 53 tiga kali lipat, runtime 50c

Tiga A, B, C hingga 100.000
1 + 8 = 9
1 + 80 = 81
1 + 242 = 243
1 + 288 = 289
1 + 512 = 513
1 + 2400 = 2401
1 + 4374 = 4375
1 + 5831 = 5832
1 + 6560 = 6561
1 + 6655 = 6656
1 + 6859 = 6860
1 + 12167 = 12168
1 + 14336 = 14337
1 + 57121 = 57122
1 + 59048 = 59049
1 + 71874 = 71875
3 + 125 = 128
3 + 65533 = 65536
5 + 1024 = 1029
7 + 32761 = 32768
9 + 15616 = 15625
9 + 64000 = 64009
10 + 2187 = 2197
11 + 3125 = 3136
13 + 243 = 256
28 + 50625 = 50653
31 + 19652 = 19683
37 + 32768 = 32805
49 + 576 = 625
49 + 16335 = 16384
73 + 15552 = 15625
81 + 1250 = 1331
121 + 12167 = 12288
125 + 2187 = 2312
125 + 50176 = 50301
128 + 59049 = 59177
169 + 58880 = 59049
243 + 1805 = 2048
243 + 21632 = 21875
289 + 6272 = 6561
343 + 59049 = 59392
423 + 16384 = 16807
507 + 32768 = 33275
625 + 2048 = 2673
1331 + 9604 = 10935
1625 + 16807 = 18432
28561 + 89088 = 117649
28561 + 98415 = 126976
3584 + 14641 = 18225
6561 + 22000 = 28561
7168 + 78125 = 85293
8192 + 75843 = 84035
36864 + 41261 = 78125

Dengan N = 1.000.000, kami hanya memiliki 102 "tiga kali lipat", daftar lengkap diberikan di bawah spoiler.

Tiga A, B, C hingga 1.000.000
1 + 8 = 9
1 + 80 = 81
1 + 242 = 243
1 + 288 = 289
1 + 512 = 513
1 + 2400 = 2401
1 + 4374 = 4375
1 + 5831 = 5832
1 + 6560 = 6561
1 + 6655 = 6656
1 + 6859 = 6860
1 + 12167 = 12168
1 + 14336 = 14337
1 + 57121 = 57122
1 + 59048 = 59049
1 + 71874 = 71875
1 + 137780 = 137781
1 + 156249 = 156250
1 + 229375 = 229376
1 + 263168 = 263169
1 + 499999 = 500000
1 + 512000 = 512001
1 + 688127 = 688128
3 + 125 = 128
3 + 65533 = 65536
5 + 1024 = 1029
5 + 177147 = 177152
7 + 32761 = 32768
9 + 15616 = 15625
9 + 64000 = 64009
10 + 2187 = 2197
11 + 3125 = 3136
13 + 243 = 256
13 + 421875 = 421888
17 + 140608 = 140625
25 + 294912 = 294937
28 + 50625 = 50653
31 + 19652 = 19683
37 + 32768 = 32805
43 + 492032 = 492075
47 + 250000 = 250047
49 + 576 = 625
49 + 16335 = 16384
49 + 531392 = 531441
64 + 190269 = 190333
73 + 15552 = 15625
81 + 1250 = 1331
81 + 123823 = 123904
81 + 134375 = 134456
95 + 279841 = 279936
121 + 12167 = 12288
121 + 255879 = 256000
125 + 2187 = 2312
125 + 50176 = 50301
128 + 59049 = 59177
128 + 109375 = 109503
128 + 483025 = 483153
169 + 58880 = 59049
243 + 1805 = 2048
243 + 21632 = 21875
289 + 6272 = 6561
338 + 390625 = 390963
343 + 59049 = 59392
423 + 16384 = 16807
507 + 32768 = 33275
625 + 2048 = 2673
864 + 923521 = 924385
1025 + 262144 = 263169
1331 + 9604 = 10935
1375 + 279841 = 281216
1625 + 16807 = 18432
2197 + 583443 = 585640
2197 + 700928 = 703125
3481 + 262144 = 265625
3584 + 14641 = 18225
5103 + 130321 = 135424
6125 + 334611 = 340736
6561 + 22000 = 28561
7153 + 524288 = 531441
7168 + 78125 = 85293
8192 + 75843 = 84035
8192 + 634933 = 643125
9583 + 524288 = 533871
10816 + 520625 = 531441
12005 + 161051 = 173056
12672 + 117649 = 130321
15625 + 701784 = 717409
18225 + 112847 = 131072
19683 + 228125 = 247808
24389 + 393216 = 417605
28561 + 89088 = 117649
28561 + 98415 = 126976
28561 + 702464 = 731025
32768 + 859375 = 892143
296875 + 371293 = 668168
36864 + 41261 = 78125
38307 + 371293 = 409600
303264 + 390625 = 693889
62192 + 823543 = 885735
71875 + 190269 = 262144
131072 + 221875 = 352947
132651 + 588245 = 720896


Sayangnya, program masih berjalan lambat, saya tidak menunggu hasil untuk N = 10.000000, waktu perhitungan lebih dari satu jam (mungkin saya membuat kesalahan dengan optimasi algoritma di suatu tempat, dan saya bisa melakukan yang lebih baik).

Yang lebih menarik untuk melihat hasilnya secara grafis:



Pada prinsipnya, sangat jelas bahwa ketergantungan dari jumlah tiga kali lipat yang mungkin pada N tumbuh terasa lebih lambat daripada N itu sendiri, dan kemungkinan hasilnya akan konvergen ke beberapa nomor tertentu untuk setiap Ξ΅. Ngomong-ngomong, dengan peningkatan Ξ΅, jumlah "tiga kali lipat" menurun secara nyata, misalnya, untuk Ξ΅ = 0,4 kita hanya memiliki 2 persamaan untuk N <100000 (1 + 4374 = 4375 dan 343 + 59049 = 59392). Jadi secara umum, tampaknya teorema itu benar-benar berlaku (well, dan mungkin itu sudah diuji pada komputer yang lebih kuat, dan mungkin semua ini sudah lama dihitung).

Mereka yang ingin dapat bereksperimen sendiri, jika ada yang memiliki hasil untuk angka 10.000.000 dan lebih tinggi, saya akan dengan senang hati menambahkannya ke artikel. Tentu saja, akan menarik untuk "menghitung" sampai saat ketika set "tiga kali lipat" benar-benar berhenti tumbuh, tetapi bisa memakan waktu yang sangat lama, kecepatan perhitungan tampaknya tergantung pada N sebagai N * N (atau mungkin N ^ 3), dan prosesnya sangat panjang Namun demikian, hal yang luar biasa ada di dekatnya, dan mereka yang berharap dapat bergabung dengan pencarian.

Sunting: seperti yang disarankan dalam komentar, Wikipedia sudah memiliki tabel dengan hasil - dalam kisaran N hingga 10 ^ 18 jumlah "tiga kali lipat" masih terus bertambah, sehingga "akhir" set belum ditemukan. Semua lebih menarik - intriknya masih dipertahankan.

Source: https://habr.com/ru/post/id427091/


All Articles