Homepage von Lars Fischer

Aus dem Ankündigungsposter zur Spring School:

Mit einer Förderung durch die Exzellenzinitiative des Bundes und der Länder führt die RWTH Aachen die Spring School »Mathematik mit SAGE« durch.

SAGE ist ein neues Computer-Algebra-System. Die drei Haupteigenschaften dieses Systems sind:

In diesem Kompaktkurs wollen wir uns mit dem Gebrauch von SAGE bekannt machen, indem wir in sechs 90-minütigen Sitzungen an verschiedenen Projekten arbeiten.

Das Beispiel der Abbildungs-Klasse:

def show_partitions(N):
    """
    Print the partitions of all natural numbers <=N.
    """
    for n in range(1,N+1):
        print partitions_list(n)
    


def list_red_pols(b):
    """
    Print all reducible polynomials of degree <= 3
    over ZZ whose coefficients are nonnegative and < b.
    """
    R. = PolynomialRing (QQ)
    for c in mrange([b,b,b]):
        f = R(c)
        if f != 0 and false == f.is_irreducible():
            print factor(f)


# Allgemeine Hinweise:
# --------------------

# An die Leute, die von Windows kommen:
#   unbedingt im emacs im Menue unter Options, C-x/C-c/C-v Cut and Paste (CUA) aktivieren
#   auf "M-/" (aka "ALT+SHIFT+7" ) als dynamische Word-Ergaenzung hinweisen (spart Tipparbeit)
#   


# .__K ohne get und set Methode ist innerhalb dieser Datei moeglich
# in der laufenden Sage-Console erzeugt eine abb1.__K die Fehlermeldung ...
#    siehe http://www.python.org/doc/faq/programming/#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam
# in der laufenden Sage-Console kommen wir nur mit den get und set Methoden an __K

# Zeichenketten, die von drei Anfuehrungszeichen, also """ """ oder ''' '''
# begrenzt sind, duerfen Zeilenumbruech enthalten.

# Es gibt einen Patch fuer eine kommende Version von SAGE, der auch
# Umlaute ermoeglicht.

# Wie arbeitet man mit mehreren Leuten an einem gemeinsamen Projekt?
#   Eine Datei pro Objekt und ein Objekt wird nur von einer Person programmiert
#   Alternative eine Datei pro Person und darin nur die Objekte die von dieser
#   Person bearbeitet werden
#   Ansonsten verliert ihr den Ueberblick
#   (CVS und Subversion fuehren zu weit, waeren aber die Loesung.)

class Abbildung(SageObject):
    """
    A class describing a map from a finite field into
    itself.

    EXAMPLE
      sage: K. = GF(5^3)
      sage: P. = PolynomialRing (K)
      sage: abb = Abbildung ( t^4+a*t+3)
      sage: abb 
      Abbildung von Finite Field in a of size 5^3 nach Finite Field in a of size 5^3
      sage: abb.valueAt (K(4))
      4*a + 4
    """

    def __init__(self, object):
        """
        INPUT:
          object -- a dictionary or a polynomial describing the map.  
        """
        if isinstance( object, dict):
            d = {}
            for x in object.keys():
                v = object[x]
                if v != 0:
                    d[x] = v
        elif isinstance( object, sage.rings.polynomial.polynomial_element_generic.Polynomial_generic_dense_field):
            d = {};
            f = object;
            self.__K = f.base_ring()
            for x in self.__K:
                v = f(x)
                if v != 0:
                    d[x] = v
        else: 
            raise TypeError, "%s: neither a dict nor or polynomial" %object
        self.__d = d

        
    def _repr_(self):
        return "Abbildung von %s nach %s" %(self.__K,self.__K)


    def valueAt( self, x):
        ""
        if self.__d.has_key(x):
            return self.__d[x]
        return K(0)

# ---------------------------------------------------------------

    def __add__(self, g):
        """Punktweise Addition einer Abbildung  g zu self.

        INPUT:
            g -- Abbildung ueber dem gleichen Ring, wie self

        EXAMPLES:
            sage: K. = GF(5^3)
            sage: P. = PolynomialRing (K)
            sage: f = Abbildung ( t^4+a*t)
            sage: g = Abbildung ( t+3 )
            sage: h = f + g
        """
        if self.__K != g.__K:
            raise ValueError, "Die beiden Abbildungen sind ueber unterschiedlichen Ringen."
        else:
            d = {}

            for x in K:
                v = self.valueAt(x) + g.valueAt(x)

                if v != K(0):
                    d[x] = v

            A= Abbildung(d)
            A.__K= self.__K
            # obige Zeile kommt noch oft. wir koennten __init__ erweitern, so
            # dass wir auch K als Argument uebergeben koennen.
            # Dann  koennten wir in einer Zeile zusammenfassen:
            # return Abbildung(d, K) 

            return A
    # end of __add__()


    # nur rechts-Mul mit Skalaren
    def __mul__(self, g): # self ist self
        """Punktweise Multiplikation einer Abbildung  g zu self oder Multiplikation der Abbildung self mit einem Skalar g.

        Die Multiplikation mit einem Skalar funktioniert NUR VON RECHTS.
        (Sonst: siehe Kapitel 11: http://www.sagemath.org/doc/html/ref/node61.html
         auch die Kapitel ueber die anderen Strukturen, Gruppen, Ringe, etc.)

        INPUT:
            g -- Abbildung ueber dem gleichen Ring, wie self oder ein Skalar aus self.__K
            
        EXAMPLES:
            sage: K. = GF(5^3)
            sage: P. = PolynomialRing (K)
            sage: f = Abbildung ( t + 1)
            sage: g = Abbildung ( 2 * t )
            sage: h = f * g
            sage: f2= f * 2
        """
        if not (isinstance(g, Abbildung) or
                (g in self.__K)  ):
            raise ValueError, "Abbildungen duerfen nur mit Abbildungen oder Ringelementen multipliziert werden"
        # nun haben wir eine Abbildung oder einen Skalar auf der rechten Seite:

        d= {}
        A= None
        
        if g in self.__K:
            # Wahr, falls rechts ein Skalar aus dem richtigen Ring steht
            # Unwahr, falls rechts eine Abbildung steht
            
            for x in K:
                v = self.valueAt(x) * g
                if v != K(0):
                    d[x] = v
                A= Abbildung(d)
        else: # ab hier stehen links und rechts Abbildungen
            if self.__K != g.__K:
                raise ValueError, "Die beiden Abbildungen sind ueber unterschiedlichen Ringen."
            else:

                for x in K:
                    v = self.valueAt(x) * g.valueAt(x)

                    if v != K(0):
                        d[x] = v

                A= Abbildung(d)
                
        A.__K= self.__K # hier heisst self, ja self
        return A
    # end of __mul__()


    def composition(self, g):
        r"""Komposition einer Abbildung g mit self: self \circ g.

        INPUT:
            g -- Abbildung ueber dem gleichen Ring, wie self
            
        EXAMPLES:
            sage: K. = GF(5^3)
            sage: P. = PolynomialRing (K)
            sage: f1 = Abbildung ( t+1)
            sage: g1 = Abbildung ( t )
            sage: h1 = f.composition(g)
            sage: f2 = Abbildung ( t*2)
            sage: g2 = Abbildung ( t + 1 )
            sage: h2 = f.composition(g)
        """
        if not self.__K == g.__K:
            raise ValueError, "Die beiden Abbildungen sind ueber unterschiedlichen Ringen."
        else:
            d={}
            A=None
            
            for x in K:
                y= g.valueAt(x)
                z= self.valueAt(y)
                if z != 0:
                    d[x]= z

            A=Abbildung(d)
            A.__K= self.__K
            
            return A
    # endo of composition()
            
            
    def is_bijective(self):
        r"""Prueft, ob self bijektiv ist.

        OUTPUT:
            boolean -- True, falls die Abbildung self bijektiv ist, sonst False
            
        EXAMPLES:
            sage: K. = GF(5^3)
            sage: P. = PolynomialRing (K)
            sage: f= Abbildung(t*2)
            sage: g= Abbildung((t+1)*(t-1))
            sage: f.is_bijective()
            True
            sage: g.is_bijective()
            False

        NOTES:
            self ist eine Abbildung ueber einem endlichen Koerper in sich selbst.
            self ist eine Liste x_i -> y_i (es fehlen nur die Paare, fuer die y_i = 0 ist).
            Wir vergleichen die Laenge der Liste uniq( [... y_i ... ] ) (die Hilfe von uniq? anschauen)
            mit der Anzahl der Elemente im Ring self.__K.
            
        """
        AnzahlElementeInK = len(self.__K) # oder auch len(list( self.__K )) oder self.__K.order()
        ListeDerWerte= list( self.__d.itervalues() )
        UniqueListe=uniq(ListeDerWerte) # uniq? mal anschauen
        
        if len(UniqueListe) + 1 == AnzahlElementeInK : # in ListeDerWerte fehlen die Nullen
            return True
        else:
            return False
        # oder auch: "return (len(UniqueListe) + 1) == AnzahlElementeInK"
    # end of is_bijective()
        

    def inverse(self):
        r"""Die Umkehrabbildung von self.

        OUTPUT:
            Abbildung -- die Umkehrabbildung von self
            
        EXAMPLES:
            sage: K. = GF(5^3)
            sage: P. = PolynomialRing (K)
            sage: f= Abbildung(t + 2)
            sage: g= f.inverse()
            sage: r= K.random_element()
            sage: g.valueAt(f.valueAt( r )) == r
            True
        """
        
        if not self.is_bijective():
            raise ValueError, "In inverse(), die Abbildung ist aber nicht bijektiv."
        else:
            d={}
            A=None

            for x in K:
                if x != 0:
                    v= self.valueAt(x) # valueAt und damit v nimmt auch den Wert 0 an
                    d[v] = x

            A= Abbildung(d)
            A.__K = self.__K
            return A
    # end of inverse()
    
# end of class Abbildung

# wir koennen die EXAMPLES Abschnitte aus obigen Dokumentations-String
# automatisch testen lassen:
# 
# ~/SpringSchool] sage -t example.sage
# sage -t  example.sage
# Example 0 (line 37)
# Example 1 (line 89)
# Example 2 (line 125)
# Example 3 (line 173)
# Example 4 (line 208)
# Example 5 (line 243)
#          [11.0 s]
#
# ----------------------------------------------------------------------
# All tests passed!
# Total time for all tests: 11.0 seconds



# wenn sage die Datei neu einliest (Return auf leerer Zeile) dann
# werden diese Anweisungen ausgefuehrt, dadurch spare ich mir das
# wiederholte anlegen von abb1 und abb2, etc
if __name__ == "__main__":
    print "Tests fuer die Abbildungsklasse:"
    K. = GF(5^3)
    P. = PolynomialRing (K)
    abb1 = Abbildung ( t^4+a*t+3)
    abb2 = Abbildung ( t^3+2*a*t+1)
    abb3 = abb1 + abb2
    abb4 = abb1 * abb2
    abb5 = abb2 * K(3)

    abb6= Abbildung(2*t)
    abb7= Abbildung(t+1)
    abb8= abb7.composition(abb6)


    #for x in K: 
        #print abb3.valueAt(x) == abb1.valueAt(x) + abb2.valueAt(x) 
        #print abb4.valueAt(x) == abb1.valueAt(x) * abb2.valueAt(x) 
        #print abb5.valueAt(x) == abb2.valueAt(x) * 3
        #print x, ':', abb6.valueAt(x),',', abb8.valueAt(x)

    abb9= Abbildung(t*2)
    abb10=Abbildung((t+1)*(t-1))
    print "Abbildung 9:" , abb9.is_bijective()
    print "Abbildung 10:", abb10.is_bijective()

    inv=abb9.inverse()
    for x in K:
        print x == inv.valueAt(abb9.valueAt(x)) 




    

nach oben

Letzte Änderung: 26.02.2009
© Lars Fischer

Valid XHTML 1.1!  Valid CSS!