B Laboratorio con PARI / GP B.� Introduzione a PARI / GP ���� / �� è una libreria per linguaggi ad alto livello (ad es. C, C++, Pascal, Fortran) ed una so�sticata calcolatrice programmabile. Le sue caratteristiche principali sono l’essere un programma libero, la rapidità (Da �� a ���� volte più rapido di altri programmi), la possibilità di usare tipi di dati comuni nell’uso matematico, l’esteso supporto per la teoria dei numeri. ���� / �� funziona su molte versioni di Unix (inclusi Linux e OS/X) e anche su Windows; può Essere scaricato liberamente da http://pari.math.u-bordeaux.fr. Da terminale invochiamo il programma come gp. Per avere una schermata di aiuto, digitiamo ? seguito da <invio>: in particolare ?<funzione> ci dà una spiegazione ? della funzione <funzione> , ?? mostra il manuale di ���� / ��, ?\ mostra i comandi di ?? con�gurazione di ���� / ��. Tra questi segnaliamo \l per salvare una copia della sessione \l in pari.log oppure \r<nome_file> per leggere il �le <nome_file> . \r B.� Introduzione alla crittografia Per prima cosa, ci occorre stabilire un metodo per associare ad una stringa, cioè Ad una sequenza di caratteri, un numero. Identi�chiamo l’alfabeto di �� lettere {A, B, . . . , Z} con Z���Z: ad A associamo �, a B associamo �, e così via, �no a Z che associamo a ��. Il modulo crypto.gp, scaricabile da http://www.mat.unimi.it/users/otto/ mepvs, de�nisce alcune funzioni a questo scopo: s2i trasforma i caratteri {A, a} in �, {B, b} in �, �no a {Z, z} in ��; e qualsiasi altro carattere in �� (in altre parole, sostituisce una X a punti, spazi, ecc.). La funzione i2s trasforma l’intero � nel carattere a, e così via ? \r crypto ? s2i("A") %1 = 0 ? s2i("H") %2 = 7 ? s2i(",") %3 = 23 ? i2s(23) %4 = "x" In realtà, per poter lavorare più comodamente su blocchi di testo, s2i accetta anche stringhe di più caratteri, che interpreta in base �� con la cifra meno signi�cativa a sinistra: ad esempio, poiché m = ��, a = �, t = ��, e = �, la stringa mate vale �� + � ⋅ �� + �� ⋅ ��� + � ⋅ ��� = �����: ? s2i("mate") %5 = 83160 �� s2i i2s B Laboratorio con PARI / GP ? i2s(83160) %6 = "mate" Occorre notare, però, che così facendo s2i non è più iniettiva neanche sulle stringhe formate da sole lettere minuscole: così come possiamo aggiungere un numero arbitrario di zeri all’inizio di un espansione decimale, possiamo aggiungere un numero arbitrario di a alla �ne di una stringa senza modi�carne il valore: ? print([s2i("m"), s2i("ma"), s2i("maaa")]) [12, 12, 12] Fortunatamente il problema è solo apparente: se vogliamo elaborare ℓ caratteri alla volta, non possiamo accettarne un numero inferiore: se ℓ = �, solo maaa è accettabile. Per potere invertire correttamente s2i, la funzione i2s ha un parametro opzionale, che stabilisce la dimensione del blocco: ? print([i2s(12), i2s(12,2), i2s(12,4)]) ["m", "ma", "maaa"] s2v In�ne, per poter cifrare e decifrare più comodamente delle frasi, il pacchetto crypto de�nisce anche la funzione s2v: se s è una stringa ed ℓ un intero (se ℓ = �, possiamo ometterlo), s2v(s, ℓ) restituisce un vettore ottenuto dividendo s in blocchi di lunghezza ℓ e considerando ciascuno come intero in base �� ? s2v("mate") %7 = [12, 0, 19, 4] ? s2v("mate",2) %8 = [12, 123] ? s2v("mate",3) %9 = [12856, 4] v2s La funzione inversa è v2s: ? v2s([12, 0, 19, 4]) %10 = "mate" ? v2s([12, 123],2) %11 = "mate" ? v2s([12856,4],3) %12 = "mateaa" Cesare cesare Il pacchetto crypto contiene, come esempio, un’implementazione dell’algoritmo di Cesare. Per comodità abbiamo de�nito due funzioni: la prima, cesare_, agisce sui numeri, mentre la seconda, cesare, agisce sulle stringhe cesare_(t, key=3) = return( (t + key) % 26) { cesare(s, key=3) = local(v, V); v = s2v(s, 1); V = vector(#v, i, cesare_(v[i], key)); return(v2s(V)) } �� B.� Introduzione alla crittogra�a Spiegazione del codice. La funzione cesare_, molto semplicemente, somma la chiave al testo modulo ��. Notiamo solo che la somma va messa fra parentesi perché l’operatore % ha una precedenza maggiore. La funzione cesare, invece, prende come argomento una stringa, la divide nel vettore v, e poi crea un nuovo vettore V ottenuto da v applicando cesare_ ad ogni elemento. L’operatore # è un abbreviazione di length, la lunghezza di un vettore. Le parentesi gra�e che circondano la de�nizione di cesare sono necessarie: tra l’altro permettono di andare impunemente a capo. length Vediamo ora qualche esempio ? cesare("Questa e’ una prova",3) %13 = "txhvwdahaaxqdasuryd" ? cesare("txhvwdahaaxqdasuryd",-3) %14 = "questaxexxunaxprova" ? cesare("txhvwdahaaxqdasuryd",26-3) %15 = "questaxexxunaxprova" Notiamo come la funzione di decifrazione non sia altro che quella di cifrazione con la chiave cambiata di segno. Cifrario affine Implementiamo il cifrario a�ne: c = k� t + b mod ��. Per prima cosa mostriamo il contenuto delle funzioni cesare e cesare_: ? ?cesare cesare(s, key=3) = local(v, V); v=s2v(s,1); V=vector(#v,i,cesare_(v[i],key));return(v2s(V)) ? ?cesare_ cesare_(t, k=3) = return((t+k)%26) Facendo copia e incolla modi�chiamo le due funzioni creando le funzioni affine e affine_ affine ? affine(s, key=[3,2]) = local(v, V); v=s2v(s,1);\ V=vector(#v,i,affine_(v[i],key));return(v2s(V)) ? affine_(t,k=[3,2]) = return((k[1]*t+k[2])%26) Proviamo ora a cifrare, con le chiavi di default, un semplice brano, dopodiché contiamo le occorrenze c = affine("Nelmezzodelcammindinostravitamiritrovaiperunavalleoscurachel adirittaviaerasmarrita") %16 = "dlzblbbfjlzhdbbtdjtdfnpldttpdbtltplftdthllrddtdzzlfnhrldhrlzdjtltppdttdlldnbdlltpd" ? s=s2v(c) %17 = [3, 11, 25, 1, 11, 1, 1, 5, 9, 11, 25, 7, 3, 1, 1, 19, 3, 9, 19, 3, 5, 13, 15, 11, 3, 19, 19, 15, 3, 1, 19, 11, 19, 15, 11, 5, 19, 3, 19, 7, 11, 11, 17, 3, 3, 19, 3, 25, 25, 11, 5, 13, 7, 17, 11, 3, 7, 17, 11, 25, 3, 9, 19, 11, 19, 15, 15, 3, 19, 19, 3, 11, 11, 3, 13, 1, 3, 11, 11, 19, 15, 3] ? dist=vector(26) �� B Laboratorio con PARI / GP %18 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ? for(i=1, #s, dist[s[i]+1] += 1) ? dist %19 = [10, 16, 13, 17, 3, 4, 0, 10, 3, 8, 2, 19, 5, 7, 7, 10, 0, 3, 4, 14, 0, 1, 0, 1, 0, 7] ? ploth(i=1,26,dist[floor(i)]) %20 = [1.0000000000000000000, 26.000000000000000000, 0.E-307, 13.00000000000000000 ? affine1(s,k)=return(affine(s,[1/k[1] % 26, - k[2]/k[1] % 26])) ? affine1(c,[3,2]) %21 = "nelmezzodelcammindinostravitamiritrovaiperunavalleoscuracheldirittaviaerasm ? affine1(s,[3,19]) %22 = "qhophccrghofdpplqglqrvwudylwdplulwurydlshuxqdydoohrvfxudfkhoglulwwdyldhudvp Hill RSA Vogliamo ora implementare ���. Per prima cosa scegliamo due primi e facciamone il prodotto: per semplicità usiamo dei valori irrealisticamente piccoli ? p = prime(100) %23 = 541 ? q = prime(105) %24 = 571 ? n = p*q %25 = 308911 ? log(n)/log(26) %26 = 3.879813977574394819241530199 prime eulerphi La funzione prime(i) restituisce l’i-esimo primo, che dev’essere però tra quelli precalcolati all’avvio. L’ultima operazione ci mostra che �log�� n� = �; cioè che, con questi paramentri, possiamo cifrare al più gruppi di tre lettere. Dobbiamo ora trovare un’esponente e che sia relativamente primo a φ(n): per quanto ���� / �� includa una funzione eulerphi per calcolare la φ di Eulero, ricordiamo che il suo calcolo è equivalente a fattorizzare n. ? phi=(p-1)*(q-1) %27 = 307800 ? e = 3; gcd (e, phi) %28 = 3 ? e = 5; gcd (e, phi) %29 = 5 ? e = 7; gcd (e, phi) %30 = 1 È chiaro che e non può essere pari; facendo un po’ di prove, vediamo che e = � è accettabile. Prendiamo pertanto (n, e) come chiave pubblica e cifriamo il testo mai: ? t = s2i("mai") %31 = 5420 ? c = Mod(t, n)^e �� B.� Introduzione alla crittogra�a %32 = Mod(288509, 308911) ? c = lift(c) %33 = 288509 ? i2s(c,4) %34 = "nukq" Per quanto per numeri di questa entità non faccia alcuna di�erenza, è importante calcolare c prima come intero modulare e dopo sollevarlo, con la funzione lift, ad un intero. Notiamo in�ne che c > ��� , ed infatti va rappresentato con quattro caratteri. Proviamo ora a decifrare nukq ? d = Mod(e, phi)^(-1) %35 = Mod(87943, 307800) ? d = lift(d) %36 = 87943 ? c = s2i("nukq") %37 = 288509 ? t = lift( Mod(c, n)^d ) %38 = 5420 ? i2s(t, 3) %39 = "mai" Mettiamo tutte queste operazioni insieme e de�niamo una funzione rsa_. Per analogia con cesare_, la chiave è un argomento unico: in questo caso un vettore contente n e d. ? rsa_(t, key) = local(n = key[1], e = key[2], c); \ c = lift( Mod(t,n)^e ); return(c) ? rsa_(5420, [n, e]) %40 = 288509 ? rsa_(288509, [n,d]) %41 = 5420 Notiamo come, ancora una volta, la funzione di decifrazione è quella di cifrazione usata con una chiave diversa. Per terminare, decifriamo con gli stessi parametri di sopra il testo zvrhupco. Per prima cosa dividiamo il testo in due blocchi di quattro lettere e leggiamo ciascuno come un numero ? s2v("zvrhupco",4) %42 = [135095, 247826] Applichiamo rsa_ a ciascun componente ? rsa_(135095, [n,d]) %43 = 9001 ? rsa_(247826, [n,d]) %44 = 9966 Ed in�ne convertiamo i due numeri in una stringa, ricordando che ciascun blocco ha lunghezza tre ? v2s([9001,9966],3) %45 = "finito" �� lift B Laboratorio con PARI / GP B.� Numeri primi, compositi e fattorizzazione Numeri di Fermat L’n-esimo numero di Fermat è F(n) = �� + �. Fermat aveva a�ermato che F(n) è un numero primo per ogni n, dopo avere osservato che ciò vale per n � �. n ? F(n)=2^(2^n)+1 ? F(1) %1 = 5 ? F(2) %2 = 17 ? F(3) %3 = 257 ? F(4) %4 = 65537 È chiaro che F(�), F(�), F(�) sono primi. Veri�chiamo che lo sia anche F(�) cercandone tutti i divisori ? n=F(4); for(d=1, n, if(n%d == 0, print(d))) 1 65537 Il quinto numero di Fermat F(�) non è primo: ? n=F(5); for(d=1, n, if(n%d == 0, print(d))) 1 641 6700417 Siamo però costretti a interrompere la ricerca perché non si conclude presto: ciò perché √ stiamo provando tutti i divisori d < n quando sarebbe su�ciente provare i divisori d < n ? n=F(5); for(d=1, sqrt(n), if(n%d == 0, print(d))) 1 641 ? n/641 %5 = 6700417 ? n=641; for(d=1, sqrt(n), if(n%d == 0, print(d))) 1 ? n=%5; for(d=1, sqrt(n), if(n%d == 0, print(d))) 1 Quindi F(�) = ��� ⋅ ������� dove entrambi i fattori sono primi. Il test di Fermat applicato a F(�) ci dice che ? Fermat(2,F(5)) %6 = 1 ? Fermat(3,F(5)) %7 = 0 Quindi � è un falso testimone per F(�), mentre � è un testimone per la compositezza di F(�). �� B.� Numeri primi, compositi e fattorizzazione ? Fermat(2,F(6)) %8 = 1 ? Fermat(3,F(6)) %9 = 0 Quindi neanche F(�) è primo: quali sono i suoi fattori? ? n=F(6); for(d=1, sqrt(n), if(n%d == 0, print(d))) 1 274177 ^C *** for: user interrupt after 22,442 ms. ? c6=F(6)/274177; for(d=1, sqrt(n), if(n%d == 0, print(d))) 1 ^C *** if: user interrupt after 10,906 ms. Abbiamo così scoperto che F(�) = ������c� dove ������ è necessariamente primo (perché?) ma non sappiamo se c� è composito. Test di Fermat Ricordiamo che Teorema B.� (di Fermat) Se n è primo, a n−� ≡ � mod n per ogni intero a con ���(a, n) = �. De�niamo allora un test di Fermat e veri�chiamo che vale per ogni base se n = �� ? Fermat(a,n)=Mod(a,n)^(n-1)==1 ? Fermat(2,11) %10 = 1 ? for(a=2,11,print(a,"\t",Fermat(a,11))) 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 0 Applichiamo il test di Fermat a F(�), ottenendo così conferma che è composito: ? n=F(6) %11 = 18446744073709551617 ? Fermat(2,n) %12 = 1 ? Fermat(3,n) %13 = 0 Per capire se c� è composito, applichiamo il test di Fermat a qualche base �� B Laboratorio con PARI / GP ? Fermat(2,c6) %14 = 1 ? Fermat(3,c6) %15 = 1 ? Fermat(5,c6) %16 = 1 for(i=1, 100, a=random(c6); if(Fermat(a,c6)==0, print(a))) c� sembra essere primo, ma il test di Fermat ha il problema dei numeri di Carmichael ? n=7*11*13*41 %17 = 41041 ? for(a=1, n-1, if(gcd(a,n)==1 && Fermat(a,n)==0, print(a))) Test di Eulero Ricordiamo che Teorema B.� (Eulero) a Se n è primo, allora a(n−�)�� ≡ � � mod n n ���� / �� implementa il simbolo di Kronecker che è l’estenzione a Z × Z del simbolo di Legendre tramite la funzione kronecker ? euler(a,n) = Mod(a,n)^((n-1)/2) == kronecker(a,n) ? euler(17,n) %18 = 0 Veri�chiamo ora se c� è composito ? for(i=1, 100, a=random(c6); if(euler(a,c6)==0, print(a))) Questo ci mostra che la probabilità che c� sia composito è dell’ordine di �−��� . B.� p − � di Pollard Cerchiamo ora di fattorizzare i numeri di Fermat utilizzando l’algoritmo p − � di Pollard: Algoritmo B.� Se ���(a, n) = � e � < d = ���(a B! − �, n) < n allora d è un fattore non banale di n Per prima cosa calcoliamo B!, o meglio, m = mcm{�, �, . . . , B} dopo aver �ssato B = ����� ? mcm(a,b)=a*b/gcd(a,b) ? m=1 %1 = 1 ? B=10000 %2 = 10000 ? for(i=1, B, m = mcm(m,i)); m+0. �� %3 = 5.793339670287642968692270879 E4348 ? B!+0. %4 = 2.846259680917054518906413212 E35659 B.� X � + Y � = n Dopodiché applichiamo l’algoritmo con basi piccole: ? n=F(6) %5 = 18446744073709551617 ? Mod(2,n)^m-1 %6 = Mod(0, 18446744073709551617) ? Mod(3,n)^m-1 %7 = Mod(5275533187106939030, 18446744073709551617) ? gcd(%,n) %8 = Mod(274177, 18446744073709551617) ? n/lift(%) %9 = 67280421310721 Abbiamo così recuperato rapidamente i due fattori primi che già conoscevamo. Il test non funziona per F(�) né F(�), ma trova rapidamente un fattore di F(�). ? n=F(7) %10 = 340282366920938463463374607431768211457 for(i=1,100, d=lift(gcd(Mod(random(),n)^m-1, n)); if (d>1 && d<n, print(d))) ? n=F(8) %11 = 115792089237316195423570985008687907853269984665640564039457584007913129639937 ? for(i=1,100, d=lift(gcd(Mod(random(),n)^m-1, n)); if (d>1 && d<n, print(d))) ? n=F(9) %12 = 1340780792994259709957402499820584612747936582059239337772356144372176403007354697680187429816690 ? for(i=1,100, d=lift(gcd(Mod(random(),n)^m-1, n)); if (d>1 && d<n, print(d))) 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 2424833 B.� X � + Y � = n C n (Z) Sia C n la curva a�ne de�nita dall’equazione X � + Y � = n, con n intero: lo scopo del laboratorio è formulare delle congetture sul comportamente di C n (Q) al variare di n. È evidente che se n < �, C n (R) = �, mentre C� (R) = {(�, �)}; supponiamo quindi che n ∈ N. Se n = md � con m, d interi naturali allora (a, b) ∈ C m (Q) ⇐⇒ (da, db) ∈ C n (Q) �� B Laboratorio con PARI / GP issquare test for forprime Possiamo perciò trascurare tutti i fattori quadratici di n: l’intero n è prodotto di primi distinti. Poiché è su�ciente trovare un punto razionale per ottenere tutti gli altri, iniziamo a cercare dei punti a coordinate intere sulle curve C n ; per sempli�care le cose, supponiamo pure che n sia primo. È chiaro che C� (Z) = {(±�, ±�)} e che C� (Z) = {(±�, ±�), (±�, ±�)}, mentre abbiamo visto nel paragrafo �.� che C� (Q) = �. In generale, se (a, b) ∈ C n (Z), allora {(±a, ±b), (±b, ±a)} ∈ C n (Z); inoltre (a, a) ∈ C n (Z) signi�ca che �a � = n. Supponendo n = p primo dispari ci basterà quindi individuare l’insieme {(a, b) ∈ N� ∶ a < b, a� + b� = p}. Poiché a� = p − b� < p � − a � , abbiamo che �a � < p, quindi sarà su�ciente � veri�care se l’insieme {n − a ∶ � � a < p��} contiene dei quadrati perfetti. Per fare ciò usiamo l’istruzione issquare e de�niamo una funzione test ? test(p) = local(y); for(x = 1, sqrt(p/2), if(issquare(p-x^2, &y),\ print(p, ":\t", [x,y]))) ? test(3) ? test(5) 5: [1, 2] Spiegazione del codice. La sbarra obliqua alla �ne della prima riga serve solo per andare a capo: possiamo pure scrivere tutto di seguito. Il ciclo for(x=a,b,seq) valuta seq con x che assume tutti i valori interi nell’intervallo [a, b]. La funzione issquare mette nella variabile indicata nel secondo argomento (notate la &) la radice quadrata, se esiste. La variabile y è dichiarata locale grazie a local, per evitare di modi�care una variabile eventualmente già de�nita; le altre variabili sono automaticamente locali. Possiamo calcolare ora C p (Z) per un po’ di primi. La funzione forprime è analoga a for, ma assume solo valori primi: ? forprime(p=2,100,test(p)) 2: [1, 1] 5: [1, 2] 13: [2, 3] 17: [1, 4] 29: [2, 5] 37: [1, 6] 41: [4, 5] 53: [2, 7] 61: [5, 6] 73: [3, 8] 89: [5, 8] 97: [4, 9] Congettura B.� Se C p (Z) ≠ � con p primo dispari, allora esiste un solo punto (a, b) ∈ C p (Z) con � < a < b. Congettura B.� C p (Z) = � se e solo se p ≡ � mod �. �� B.� X � + Y � = n C n (Q) Noto un punto a coordinate intere, possiamo trovare tutti i punti con coordinate razionali; non c’è motivo, però, che se C n (Z) = � allora anche C n (Q) = �. Sia C una curva de�nita su Z e sia q un primo qualsiasi, allora abbiamo una mappa, detta riduzione modulo q C(Z) (a, b) / C(Fq ) / (a mod q, b mod q) (B.�) Segue che, se C(Fq ) = � per qualche primo q, allora anche C(Z) = �. Non è possibile estendere questa mappa a C(Q) perché, ad esempio, ��q mod q non ha nessun senso. D’altro canto, se n ≡� � mod q, possiamo de�nire ��n mod q come l’unica classe di resto n′ mod q tale che nn′ ≡ � mod q: ad esempio, ��� ≡ � mod � perché � ⋅ � ≡ � mod �; in altre parole, ��n mod q = (n mod q)−� in F∗q . Sia O q = {m�n ∈ Q ∶ (m, n) ∈ Z × N, ���(m, n) = �, n ≡� � mod q} l’insieme degli interi rispetto a q. Allora possiamo de�nire una mappa Oq → Fq e quindi estendere (B.�) ad una mappa C(Oq ) → C(F p ): in questo modo possiamo sollevare informazioni su C(F p ) a informazioni su di un vasto sottoinsieme di C(Q). Per tracciare il gra�co di una curva su Fq , carichiamo il modulo diofantea.gp, che possiamo scaricare da http://www.mat.unimi.it/users/otto/mepvs ? \r diofantea ? plotmod(11,x^2+y^2-7) * C: x^2 + (y^2 - 7) ≡ 0 mod 11 ___________ 10| | 9| ** | 8| * * | 7| | 6| * * | 5| * * | 4| | 3| * * | 2| ** | 1| | 0| | ----------0 5 10 Spiegazione del codice. La funzione plotmod ha cinque argomenti, di cui solo i primi plotmod due obbligatorî: plotmod(n, p(x, y)) traccia il gra�co della curva p(x, y) = � modulo n, dove n non è necessariamente primo, mentre p è un polinomio in x ed y (è necessario usare queste variabili). La sintassi completa è plotmod(n, p� (x, y), p� (x, y), p� (x, y), arg ): p� e p� sono altri due polinomi, mentre arg = ε x + �ε y con ε x , ε y = �, �; se ε x = � allora le ascisse vanno da � a n − �, se ε x = �, le ascisse sono centrate in �; analogamente per ε y . �� B Laboratorio con PARI / GP ? * / \ A V X 0 plotmod(29,x^2+y^2-7,x,y,3) C1: x^2 + (y^2 - 7) ≡ 0 mod 29 C2: x ≡ 0 mod 29 C3: y ≡ 0 mod 29 C1 ∩ C2 C1 ∩ C3 C2 ∩ C3 C1 ∩ C2 ∩ C3 _____________________________ 14| / | 13| / | 12| / | 11| / | 10| * / * | 9| * / * | 8| */* | 7| * / * | 6| A | 5| / | 4| * / * | 3| / | 2| / | 1| * / * | 0|\\\\\\\\V\\\\\X\\\\\V\\\\\\\\| -1| * / * | -2| / | -3| / | -4| * / * | -5| / | -6| A | -7| * / * | -8| */* | -9| * / * | -10| * / * | -11| / | -12| / | -13| / | -14| / | -----------------------------10 -5 0 5 10 Fissiamo un primo p ≡ � mod �, per esempio p = �, e tracciamo il gra�co di C p modulo q per un po’ di primi q ? plotmod(2,x^2+y^2-7,0,0,3) * C: x^2 + (y^2 - 7) ≡ 0 mod 2 __ 1|* | 0| *| -0 ? plotmod(3,x^2+y^2-7,0,0,3) * C: x^2 + (y^2 - 7) ≡ 0 mod 3 �� ___ 1| * | 0|* *| -1| * | --0 ? plotmod(5,x^2+y^2-7,0,0,3) * C: x^2 + (y^2 - 7) ≡ 0 mod 5 _____ 2| | 1| * * | 0| | -1| * * | -2| | ----0 ? plotmod(7,x^2+y^2-7,0,0,3) * C: x^2 + (y^2 - 7) ≡ 0 mod 7 _______ 3| | 2| | 1| | 0| * | -1| | -2| | -3| | ------0 ? plotmod(11,x^2+y^2-7,0,0,3) * C: x^2 + (y^2 - 7) ≡ 0 mod 11 ___________ 5| * * | 4| | 3| * * | 2|* *| 1| | 0| | -1| | -2|* *| -3| * * | -4| | -5| * * | -----------5 0 5 B.� X � + Y � = n Ripetendo per ulteriori q e per vari primi p ≡ � mod � possiamo formulare la seguente Congettura B.� Sia p ≡ � mod �. Allora C p (Fq ) ha molti punti se q ≠ p, mentre C p (F p ) = {�, �}. Notiamo che la congettura implica che se (a, b) ∈ C p (Q) allora p divide il numerato�� B Laboratorio con PARI / GP Mod re o il denominatore di a e b. Possiamo fare ancora meglio, però: consideriamo la riduzione modulo p� di C p data dalla mappa C p (O p ) → C p (Z�p� Z). Se diamo il comando plotmod(49,x^2+y^2-7) vediamo che Z� (Z��� Z) = �. Lo stesso vale per p = ��, ��. È chiaro che printmod è utilizzabile solo se p è molto piccolo: sia per via del disegno, sia perché, per come è costruita, veri�ca se ogni punto del piano è una radice del polinomio. Costruiamo un’analogo modulare di test, usando Mod: ? testmod(p) = for(x=0, p-1, if( issquare(Mod(p-x^2,p^2)), print(x) ) ) ? forprime(p=3,1000,if(p%4==3,testmod(p))) ? Congettura B.� Se p ≡ � mod � è primo, allora C p (O p ) = �. In particolare, se (a, b) ∈ C p (Q) allora p divide il denominatore di a o quello di b Avendo visto che C� (Q) = �, possiamo chiederci se questo sia vero per ogni p ≡ � mod �: non avendo nessun motivo per supporlo vero, non osiamo neanche formulare una congettura. Domanda B.� Se p ≡ � mod �, allora C p (Q) = �? ��
© Copyright 2024 Paperzz