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.
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))