Reprezentowanie liczb Eisensteina bez liczb zmiennoprzecinkowych

9

Mam projekt, w którym muszę użyć pól kwadratowych. Dokładnie numery formularzaa+b3 z a,bQ.

Oto na przykład liczby pierwsze w liczbach całkowitych Eisensteina :

Nie chcę używać szałwii. Chciałbym napisać własny typ danych do włączenia numpy. PARI byłby użyteczny - ale nie jest kompatybilny z Pythonem.

  • Dodawanie tych obiektów jest dość jasne
    (a1+b13)+(a2+b23)=(a1+a2)+(b1+b2)3
  • Mnożenie jest nieco bardziej delikatne, ale możemy go również kodować na stałe
    (a1+b13)×(a2+b23)=(a1a23b1b2)+(a1b2+a2b1)3
  • Mój typ danych musi również uwzględniać podział. Dla uproszczenia weźmy wzajemność:
    1a+b3=ab3a2+3b2

Czy istnieje naturalny sposób kodowania tych operacji oparty na macierzy, podobny do tego C można napisać w kategoriach 2×2 matryce?

(abba)

Może po prostu zaprogramuję operacje jako trzykrotnie z trzema operacjami opisanymi powyżej. Jakieś pomysły?

John Mangual
źródło

Odpowiedzi:

10

Dla a+b3 możesz użyć reprezentacji

(a3bba)
Dodawanie działa oczywiście. W celu pomnożenia możesz zweryfikować
(a13b1b1a1)(a23b2b2a2)=(a1a23b1b23(a1b2+b1a2)a1b2+b1a2a1a23b1b2)
która zachowuje reprezentację, a zatem mamy homomorfizm pierścieniowy.

Biorąc wyznacznik macierzy daje (kwadrat) normę a2+3b2, zatem odwrotność odpowiada odwrotnym macierzom, zgodnie z oczekiwaniami.

Rozważałeś już użycie potrójnych , przy których zakładam, że użyłbyś liczb całkowitych i wspólnego mianownika. Takie podejście może być również przydatne w reprezentacji macierzowej.

Aktualizacja : Ogólna metoda reprezentacji macierzy wykorzystuje macierz towarzyszącą . Załóżmy na przykład, że chcesz reprezentowaća+bω zamiast tego gdzie ω=exp(2πi3)w ten sposób ω2+ω+1=0. Macierz towarzyszącaω jest (0111), i zachowuje się to we wszystkich powiązanych operacjach pierścienia, takich jak ωsamo. Oczywiście,1 może być reprezentowany jako (1001); dlatego macierzowa reprezentacjaa+bω jest

(abbab)
Możesz sprawdzić, czy jest to homomorfizm pierścieniowy. Ponadto łatwo to zobaczyć. W przypadku mnożenia odpowiednie formuły są teraz
(a1+b1ω)(a2+b2ω)=(a1a2b1b2)+(a1b2+b1a2b1b2)ω(a1b1b1a1b1)(a2b2b2a2b2)=(a1a2b1b2(a1b2+b1a2b1b2)a1b2+b1a2b1b2a1a2a1b2b1a2)
kukurydza
źródło
2

Zgaduję, że potrzebujesz dokładnej racjonalnej arytmetyki do wszystkiego, ponieważ mogą powodować błędy zmiennoprzecinkowe 1/z nie w Q[3] nawet jeśli zjest. W tym celu możesz rzucić okiem na pakiet SymPy ; jeśli nie użyjesz ich racjonalnego typu danych bezpośrednio, może to posłużyć jako inspiracja dla Twojej ręcznie rozwijanej wersji. Następnie możesz zbudować typ pola kwadratowego na dowolnym wybranym typie liczby wymiernej.

Bez względu na to, jak reprezentujesz elementy swojego pola, możesz przeciążać operatorów w Pythonie za pomocą „magicznych metod”. Zobacz także ten post SO dotyczący tworzenia własnego typu liczbowego w języku Python.

Nie sądzę, aby było o wiele więcej pracy kodującej reprezentację elementu pola kwadratowego albo jako macierz 2 x 2 liczb wymiernych, albo jako parę liczb wymiernych, ponieważ operacje arytmetyczne nie są tak skomplikowane. Podejrzewam jednak, że drugie podejście będzie szybsze.

Daniel Shapero
źródło
1
Interesujące może być porównanie praktycznej wydajności numpyprzyspieszonych operacji macierzowych z wydajnością typów danych zdefiniowanych przez użytkownika. Nie jestem pewien, kto byłby zwycięzcą.
ccorn,
Tak, to prawda, numpy ma wiele ręcznie kodowanych optymalizacji po stronie C, aby przyspieszyć. Trzeba by to przerobić samemu, aby osiągnąć ten sam efekt. Niemniej jednak najpierw powinna pojawić się funkcjonalność, a później można się martwić szybkością.
Daniel Shapero