{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. Εισαγωγή στο Sage "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 Πως τρέχουμε το Sage σε jupyter notebook "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Α. Στο Εργαστήριο ΗΥ \n",
"\n",
" \n",
" \n",
"Μπορούμε να χρησιμοποιήσουμε το Sage [εδώ](https://cloud.sagemath.com/), δίχως καμία εγκατάσταση του λογισμικού στον υπολογιστή μας, αρκεί να έχουμε σύνδεση στο διαδίκτυο. Όμως, ο server που χρησιμοποιείται γι' αυτό τον σκοπό ορισμένες φορές δεν είναι διαθέσιμος λόγω υπερφόρτωσης. \n",
" \n",
"Προτείνεται, χωρίς να είναι απαραίτητο, να χρησιμοποιήσουμε το Sage στο γραφικό περιβάλλον jupyter notebook \n",
"επειδή: α) έχετε ήδη εξοικειωθεί με το τελευταίο σε προηγούμενα μαθήματα που \n",
"διδαχτήκατε (π.χ. Python) και β) το jupyter notebook προσφέρει την δυνατότητα να \n",
"εναλλάσσουμε γρήγορα από κελί κώδικα (code) SageMath σε κελί markdown, o οποίος \n",
"προσφέρει εύκολη διαμόρφωση απλού και σύνθετου κειμένου καθώς και εισαγωγή \n",
"σχημάτων. Ακόμα περισσότερο προσφέρει διαμόρφωση μαθηματικού κειμένου, μέσω του \n",
"$\\rm\\LaTeX$, και να σώζουμε τα notebooks σε διαφορετικές μορφές (html, pdf κα). \n",
"Οι σημειώσεις και τα σχήματα σε ένα notebook έχουν καθοριστική σημασία \n",
"τόσο στην περιγραφή όσο και στην κατανόηση των μαθηματικών προβλημάτων που θα \n",
"διαπραγματευτούμε κατά την διάρκεια του μαθήματος. Επιπλέον, η χρήση κειμένου εμβόλιμα στις εντολές κώδικα του Sage βοηθά να \n",
"κατανοήσουμε καλύτερα στο τι ακριβώς κάνει η κάθε μία εντολή που χρησιμοποιούμε. \n",
"Οι σημειώσεις αυτές γράφονται στο περιβάλλον του jupyter notebook, \n",
" \n",
"χρησιμοποιώντας συνδυασμό markdown και html τα οποία είναι απόλυτα συμβατά μεταξύ τους, και η όποια επιπλέον επεξεργασία του κειμένου χρειάσθηκε έγινε με το $\\rm \\LaTeX$. Το σύνολο των προγραμμάτων που χρησιμοποιήθηκαν είναι ελεύθερα λογισμικά ανοιχτού κώδικα για το λειτουργικό σύστημα GNU/Linux με πυρήνα 3.16.7.\n",
" \n",
"Το Sage είναι ένα σύνολο λογισμικών που εκτελούν συμβολικούς υπολογισμούς.\n",
"Συστήματα που εκτελούν συμβολικούς υπολογισμούς είναι ικανά να αντιμετωπίζουν τα μαθηματικά αντικείμενα συμβολικά. Αυτό σημαίνει ότι τα μαθηματικά αντικείμενα παριστάνονται ακριβώς, και όχι προσεγγιστικά, και συνεπώς διάφορες μαθηματικές εκφράσεις στις οποίες εμφανίζονται μεταβλητές που δεν έχουν συγκεκριμένες τιμές, αφήνονται σε συμβολική μορφή. \n",
"Για παράδειγμα, αν ζητήσουμε να κατασκευασθεί ένα αριθμητικό πρόγραμμα για να \"λύσει την εξίσωση Αν επιπλέον το πρόβλημα που θέλουμε να επιλύσουμε απαιτεί υπολογισμούς που αφορούν σύνολα, συναρτήσεις, μαθηματικές εκφράσεις (πολυωνυμικές, ρητές, αλγεβρικές κλπ), γεωμετρικά χωρία, παραγωγίσεις, θεωρήματα, αποδείξεις κτλ, τότε είναι εύλογο να υποθέσει κανείς ότι ένα υπολογιστικό σύστημα που είναι ικανό να εκτελεί συμβολικούς υπολογισμούς, να έχει κάποια χρησιμότητα. Το Sage είναι ένα σύνολο λογισμικών τα οποία είνα ικανά να εκτελούν τόσο συμβολικούς υπολογισμούς, όσο και αριθμητικούς, και αναφέρεται από τα αρχικά Software for Algebra, Geometry and Experimentation. \n",
"Ορισμένα κύρια χαρακτηριστικά του Sage είναι: Στην παράγραφο αυτή αναφέρονται κάποιες έννοιες στις οποίες ο αναγνώστης ίσως να μην είναι τόσο εξοικειωμένος. Μπορείτε να συνεχίσετε στην επόμενη παράγραφο. Όμως ενθαρρύνω τον αναγνώστη να \"βουτήξει\" δίχως κανένα ενδοιασμό, όπως ακριβώς τον ενθαρρύνω να κάνει το ίδιο και με το Sage. Απλά, ας βουτήξουμε!!! \n",
"Στην Θεωρία Κωδικοποίησης και στην Κρυπτογραφία συχνά δουλεύουμε με ένα πεπερασμένο σώμα. Ένα πεπερασμένο σώμα, ή σώμα Galois, δηλώνεται με $\\mathbb{F}_{p^n}$, και έχει ένα πεπερασμένο πλήθος στοιχείων. Αποδεικνύεται ότι (μέχρι ισομορφισμού)\n",
"υπάρχει ένα και μόνο ένα πεπερασμένο σώμα που περιέχει $p^n$ στοιχεία, για κάθε δύναμη πρώτου $p$. Ο πρώτος $p$ αναφέρεται ως η χαρακτηριστική του πεπερασμένου σώματος. Τα στοιχεία του $\\mathbb{F}_{p^n}$ μπορούν να αναπαρασταθούν ως πολυώνυμα $g(x)$ βαθμού $d$, αυστηρά μικρότερου από $n$ ($d\\leq n-1$), με συντελεστές στο ελάχιστο υποσώμα $\\mathbb{F}_{p}=\\mathbb{Z}_p$. Για να κατασκευάσουμε ένα πεπερασμένο σώμα $\\mathbb{F}_{p^n}$, θεωρούμε ένα ανάγωγο πολυώνυμο $f(x)$, πάνω στο ελάχιστο υποσώμα $\\mathbb{F}_{p}$, και θεωρούμε μια πρωταρχική ρίζα $a$ του $f(x)$, δηλαδή $f(a)=0$, και $a^{p^n-1}=1$. \n",
"Αποδεικνύεται ότι η πολλαπλασιαστική ομάδα του $\\mathbb{F}_{p^n}$, είναι κυκλική (άρα και αντιμεταθετική), οπότε το σώμα έχει την αναπαράσταση $$ $$\n",
"$$\\mathbb{F}_{p^n} = \\lbrace\\, 0,\\,a,\\,a^2,\\,\\ldots, a^{p^n-1} = 1 \\rbrace\\,,$$ $$ $$\n",
" \n",
"και τότε λέμε ότι έχουμε κατασκευάσει το $\\mathbb{F}_{p^n}$ ως την αλγεβρική επέκταση $\\mathbb{F}_{p}[x]\\,/\\,f(x)$ του ελάχιστου υποσώματος $\\mathbb{F}_{p}$.\n",
" Για παράδειγμα, θεωρούμε $a\\in \\mathbb{F}_{3^2}$, πρωταρχική ρίζα του ανάγωγου πολυωνύνου $f(x)=x^2+x+2$, με συντελεστές στο $\\mathbb{Z}_3$. \n",
"Αφού $a$ ρίζα του $f(x)$, αυτό σημαίνει ότι $f(a)=0$, και άρα $a^2 = 2\\,a +1$ ($\\mod 3$). Τότε έχουμε $$ $$\n",
"$$ a^8 = (a^4)^2 = (a^2\\,a^2)^2 = (2a+1)^2 (2a+1)^2 = (4 a^2+4a+1)(4a^2+4a+1) = $$ $$ $$\n",
"$$\\quad=(2a+1+a+1)(2a+1+a+1) = (3a+2)(3a+2)=4=1 \\qquad \\mod 3\\,.$$\n",
" και τα στοιχεία του πεπερασμένου σώματος $\\mathbb{F}_{3^2}$ μπορούν να αναπαρασταθούν ως δυνάμεις του $a$, ως εξής \n",
"$$ $$\n",
"$$\\mathbb{F}_{3^2} = \\lbrace 0,a,a^2,\\ldots, a^7,1 \\rbrace \\,.$$ \n",
"Στο Sage τα παραπάνω υλοποιούνται πολύ εύκολα χρησιμοποιώντας την συνάρτηση \n",
"Το Sage δουλεύει παρόμοια όπως η Python, όμως ορισμένες φορές πρέπει να ορίζουμε τις μεταβλητές μας με ρητό τρόπο xρησιμοποιώντας την συνάρτηση Κάθε μεταβλητή στο Sage έχει έναν τύπο ( \n",
"Το Sage μας παρέχει ένα σύνολο από μαθηματικές σταθερές, όπως το \n",
"Χρησιμοποιώντας την συνάρτηση \n",
"Το Sage μας παρέχει την επιλογή να εξαγάγουμε το αποτέλεσμα ως μια λεξικογραφική λίστα, χρησιμοποιώντας το όρισμα \n",
"Κάθε όρος της τελευταίας λίστας περιέχει το όνομα της μεταβλητής και δίπλα της την αντίστοιχη τιμής της z, που ικανοποιεί την εξίσωση. Για παράδειγμα, για να επιλέξουμε την τιμή της πρώτης λύσης, εκτελούμε\n",
" \n",
"Η λεξικογραφική λίστα είναι χρήσιμη όταν θέλουμε να αντικαταστήσουμε μια συγκεκριμένη τιμή της μεταβλητής \n",
"Ας υποθέσουμε ότι δίνουμε μια συγκεκριμένη αυθαίρετη τιμή στην μεταβλητή z, π.χ. z = 3. Τότε δεν μπορούμε να έχουμε άμεση πρόσβαση στην λεξικογραφική λίστα όπως προηγουμένως, γιατί τώρα η z αναφέρεται σε μια τιμή. Όμως με την επιλογή \n",
"Δηλαδή, έστω κι αν δεν μπορούμε να χρησιμοποιήσουμε την z ως μια μεταβλητή, η προηγούμενη ιδιότητά της ως λύσης μιας εξίσωσης εξακολουθεί να περιέχεται στην λεξικογραφική λίστα \n",
"Ας υποθέσουμε ότι θέλουμε να βρούμε τις ρίζες μιας πολυωνυμικής εξίσωσης τρίτου βαθμού, όπου οι συντελεστές είναι συμβολικές εκφράσεις. Πριν προχωρήσουμε στην επίλυση του προβλήματος, επαναφέρουμε όλες τις μεταβλητές μας στην αρχική τους κατάσταση με την εντολή \n",
"Με πρώτη ματιά, οι τύποι δείχνουν αρκετά περίπλοκοι. Ας ελέγξουμε λοιπόν ότι το αποτέλεσμα που μας έδωσε το Sage είναι πράγματι σωστό, θέτοντας συγκεκριμένες απλές τιμές στις παραμέτρους a,b,c, για παράδειγμα, a=1, b=2, c=3. \n",
"Όπως παρατηρούμε το αποτέλεσμα δεν είναι αυτό που αναμέναμε. Τόσο το πολυώνυμο p, όσο και οι λύσεις εξακολουθούν να είναι σε συμβολική μορφή. Ίσως κάποιος να δοκίμαζε να ξανατρέξει τον ορισμό του πολυωνύμου p με τις τρέχοντες τιμές των παραμέτρων. Όμως αυτό δεν είναι και τόσο ικανοποιητική λύση, αφού θα μπορούσαμε να έχουμε ορίσει ένα πλήθος από συμβολικές εκφράσεις που να περιείχαν τα a, b, c, οι οποίες μάλιστα να είναι διάσπαρτες στο notebook. \n",
"\n",
"Πως λοιπόν να αναγκάσουμε το πολυώνυμο και τις λύσεις να υπολογισθούν με τις συγκεκριμένες τιμές των a,b,c; \n",
"Τώρα μάλιστα! Μπορούμε να δούμε και το πολυώνυμο και μια ρίζα του, υπολογισμένα για την συγκεκριμένη επιλογή των παραμέτρων. Επιπλέον, τώρα υπάρχει τρόπος και να υπολογίσουμε το πολυώνυμο p, όπου x να είναι η τιμή μιας ρίζας!!\n",
" \n",
"Για να ελέγξουμε αν ο αριθμός αυτός είναι πράγματι μηδέν, βρίσκουμε την αριθμητική του τιμή"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.88737914186277e-15 - 4.44089209850063e-16*I\n"
]
}
],
"source": [
"print n(p(x=s0,a=a,b=b,c=c))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Παρατηρήστε ότι τόσο το πραγματικό όσο και το φαναταστικό μέρος του προηγούμενου μιγαδικού αριθμού είναι πάρα πολύ μικροί αριθμοί, της τάξης $10^{-15}$ και $10^{-16}$, αντίστοιχα, το οποίο σημαίνει ότι είναι κοντά στο μηδέν με ακρίβεια που εκτελεί ο υπολογιστής μας.\n",
" \n",
"Επαναφέρουμε όλες τις τιμές μας στην αρχική τους κατάσταση με την συνάρτηση \n",
"δηλαδή η x αναφέρεται στην y, η y αναφέρεται στην z, και η z αναφέρεται στο 3. Μπορούμε να ανιχνεύσουμε τις αναφορικές αυτές τιμές με την εντολή \n",
"Η πρώτη χρήση της \n",
"Επειδή ανατίθεται μια συγκεκριμένη τιμή στο δεξί μέρος μιας έκφρασης, όλες οι μεταβλητές αποκτούν την ίδια τιμή 3. Για να αποτρέψουμε την ανάθεση τιμών στο δεξί μέρος χρησιμοποιούμε εισαγωγικά. \n",
"Κάθε αντικείμενο στο Sage έχει έναν τύπο. Ο τύπος ενός αντικειμένου καθορίζει τι είδους χειρισμοί μπορούν να εφαρμοσθούν στο αντικείμενο. Οι κύριοι τύποι δεδομένων στην Python είναι οι εξής: \n",
"Οι κύριοι τύποι αριθμών στο Sage είναι οι ακέραιοι, οι ρητοί, οι πραγματικοί κι οι μιγαδικοί και έχουν τις συντομεύσεις \n",
"Μπορούμε να μετατρέψουμε ένα string από 16αδική ή 8δική μορφή, σε δεκαδική μορφή \n",
"Δοσμένης μιας λίστας συντελεστών, μπορούμε να βρούμε την τιμή οποιουδήποτε αριθμού, σε κάθε βάση. \n",
"Ο αριθμός c παίρνει την λίστα των αριθμών απο το 0 μέχρι το 9 για να μας δώσει στην \n",
"γνωστή μας δεκαδική μορφή τον αριθμό\n",
"$$ 9876543210 = 0\\cdot 10^0 + 1\\cdot 10^1 + 2\\cdot 10^2 + \\ldots + 9\\cdot 10^9\\,,$$\n",
"ενώ ο αριθμός d χρησιμοποιεί την ίδια λίστα συντελεστών για να μας δώσει στην βάση του 3 τον αριθμό\n",
"$$ 250959 = 0\\cdot 3^0 + 1\\cdot 3^1 + 2\\cdot 3^2 + \\ldots + 9\\cdot 3^9$$\n",
"Ένας γρήγορος τρόπος για να έχουμε την αναπαράσταση ενός αριθμού με κινητή υποδιαστολή (floating-point) από έναν ρητό αριθμό είναι να περιοριστούμε στο σύνολο \n",
"Δεν μπορούμε άμεσα να περιoρίσουμε το pi σε έναν ρητό, γιατί\n",
" \n",
"Παρατηρήστε την διαφορά μεταξύ της τιμής 21053343141/6701487259 του y, και της τιμής 245850922/78256779 του \n",
"Αν και το \n",
"Ο τύπος του x είναι \n",
"Συχνά δουλεύουμε με εξισώσεις \n",
"Ο τύπος της εξίσωσης είναι \n",
"Στο Sage επιλέγουμε το αριστερό και το δεξί μέλος της εξίσωσης, αντίστοιχα, ως εξής:\n",
" \n",
"Εναλλακτικές εντολές της \n",
"Το επόμενο παράδειγμα είναι από το βιβλίο του πρωτεργάτη του Sage, William Stein, με τίτλο \n",
"Sage for Power Users.\n",
"\n",
"Στο Sage μπορούμε να αποθηκεύουμε έμμεσες αναφορές για συμβολικά αντικείμενα χρησιμοποιώντας συναρτήσεις ( \n",
"Για να ανιχνεύσουμε τι συμβαίνει με την συνάρτηση \n",
"Την πρώτη φορά που καλέσαμε την συνάρτηση \n",
"Με την βιβλιοθήκη \n",
"Σε αυτή την παράγραφο θα δούμε πως είναι η εσωτερική δομή εκφράσεων στο Sage σε μεγαλύτερο βάθος\n",
" \n",
"Επιβάλλαμε στις μεταβλητές x,y να αλλάξουν τύπο και να γίνουν \n",
"Με βάση την προηγούμενη έκφραση του πολυωνύμου p σε δυο μεταβλητές x,y, μπορούμε να φτιάξουμε το παρακάτω δέντρο. \n",
"
\n",
"\n",
" \n",
"\n",
"Ανοίγουμε μια οθόνη εντολών (terminal) και δημιουργούμε έναν κατάλογο (directory) στο `home` directory του λογαριασμού μας ή οπουδήποτε αλλού, δίνοντάς του ένα όνομα της αρεσκείας μας π.χ. `sagemath`.
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"
\n",
"Εναλλακτικά στο menu των προγραμμάτων έχει δημιουργηθεί μια συντόμευση που τρέχει αυτόματα την εντολή \n",
" \n",
"
\n",
"**`/opt/sage-7.4/./sage -n jupyter`**\n",
"
\n",
"Αν επιλέξετε τον δεύτερο τρόπο μην ξεχάσετε να δημιουργήσετε ένα directory στο οποίο θα σώζετε και θα αναζητάτε τα notebooks που θα δημιουργούμε στα μαθήματα! "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"### Β. Στον προσωπικό σας υπολογιστή
\n",
" \n",
"\n",
"Μπορείτε να εγκαταστήσετε το `Sage` στον προσωπικό σας υπολογιστή (Windows/Mac/Linux) ακολουθώντας τις οδηγίες [εδώ](http://www.sagemath.org/)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Γ. Στο sagemathcloud\n",
"\n",
" \n",
"\n",
"sin(x)=0
, ως προς x\", η πιο πιθανή απάντηση που θα παίρναμε θα ήταν μια ποσότητα με ακρίβεια 32-bit, την οποία το πρόγραμμα θα τύπωνε σαν 0.0
, και όχι μια απάντηση της μορφής \"{ n π | integer(n)
} \". Από μαθηματική σκοπιά, ένα λογισμικό που έχει την δυνατότητα να μας παρέχει την τελευταία συμβολική, παραμετρική μορφή, υπερέχει από ένα αντίστοιχο που μας δίνει μια και μόνη αριθμητική τιμή. Μια και μόνο αριθμητική τιμή μπορεί να είναι χρήσιμη για έναν συγκεκριμένο σκοπό, όμως όσο απλή κι αν είναι, δεν παύει να είναι ένας συμβιβασμός. \n",
"\n",
"
\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"\n",
"## 1.3 Πρώτη επαφή με το Sage.\n",
"\n",
"\n",
"Τρέχουμε τις εντολές του Sage σε jupyter notebook σε κελιά (cells) κώδικα (code
). Οι εντολές εκτελούνται πατώντας:
\n",
"\n",
"
\n",
" Ctrl-Enter
για να εκτελέσουμε το κελί που βρισκόμαστε, Alt-Enter
για να εκτελέσουμε το κελί που βρισκόμαστε και να εισαγάγουμε ένα νέο κελί αμέσως μετά,Shift-Enter
για να εκτελέσουμε το κελί που βρισκόμαστε και να επιλέξουμε το κελί αμέσως μετά.
\n",
"Επιλέγουμε για να γράψουμε μέσα σε ένα cell με Enter
, ή αριστερό click στο ποντίκι.\n",
"Στο jupyter notebook πληκτρολογούμε Ctrl-Shift-P
για να δούμε όλες τις διαθέσιμες συντομεύσεις πληκτρολογίου και διάφορες επιλογές για να επεξεργαζόμαστε τα cells καθώς και τον πυρήνα. Ορισμένες από αυτές τις επιλογές είναι διαθέσιμες και στο menu επιλογών του jupyter στο πάνω μέρος του notebook. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pi\n"
]
}
],
"source": [
"print pi"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n"
]
}
],
"source": [
"print sin(pi)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pi\n"
]
}
],
"source": [
"print(pi)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sin(pi20)
δεν είναι πλέον μηδέν.\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## 1.4 Ποιά συστήματα χρησιμοποιούνται στο Sage;"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['MPFR']\n"
]
}
],
"source": [
"from sage.misc.citation import get_systems\n",
"print get_systems('Rational(0.75)')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['MPFR', 'ginac']\n"
]
}
],
"source": [
"print get_systems('RealField(10)(pi)')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on module sage.misc.citation in sage.misc:\n",
"\n",
"NAME\n",
" sage.misc.citation - File: sage/misc/citation.pyx (starting at line 1)\n",
"\n",
"FILE\n",
" /home/tasos/sage-7.5.1/local/lib/python2.7/site-packages/sage/misc/citation.so\n",
"\n",
"DESCRIPTION\n",
" Dependency usage tracking for citations\n",
"\n",
"FUNCTIONS\n",
" get_systems(...)\n",
" get_systems(cmd)\n",
" File: sage/misc/citation.pyx (starting at line 50)\n",
" \n",
" Returns a list of the systems used in running the command\n",
" cmd. Note that the results can sometimes include systems\n",
" that did not actually contribute to the computation. Due\n",
" to caching and the inability to follow all C calls, it\n",
" could miss some dependencies as well.\n",
" \n",
" INPUT:\n",
" \n",
" - ``cmd`` - a string to run\n",
" \n",
" EXAMPLES::\n",
" \n",
" sage: from sage.misc.citation import get_systems\n",
" sage: s = get_systems('integrate(x^2, x)'); #priming coercion model\n",
" sage: get_systems('integrate(x^2, x)')\n",
" ['ginac', 'Maxima']\n",
" sage: R.underscore
παίρνουμε το αποτέλεσμα από τον αμέσως προηγούμενο υπολογισμό. Με δυο underscore
παίρνουμε το αποτέλεσμα του προτελευταίου υπολογισμού και με τρία, πριν τρεις υπολογισμούς. Περαιτέρω χρήση τους δεν είναι δυνατή. \n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Ας θεωρήσουμε τώρα ότι θέλουμε να υπολογίσουμε την διαφορά ανάμεσα στην πραγματική τιμή του $\\pi$ και την αριθμητική του τιμή με μια ακρίβεια 30 ψηφίων. Ο πιο γρήγορος τρόπος για να βρούμε την τελευταία είναι μέσω της συνάρτησης \n",
"numerical_approx
.\n",
""
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.14159265358979323846264338328\n"
]
}
],
"source": [
"print numerical_approx(pi,digits=30)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Όμως συχνά θέλουμε οι υπολογισμοί μας να εκτελούνται με καθορισμένη ακρίβεια, για παράδειγμα 30 δεκαδικών ψηφίων. Τότε χρησιμοποιούμε την συνάρτηση RealField
με δεδομένη ακρίβεια, για παράδειγμα για τον υπολογισμό του $\\pi$ με προσέγγιση 30 ψηφίων δίνουμε\n",
""
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.1415926535897932384626433833\n"
]
}
],
"source": [
"R = RealField(30*log(10,2))\n",
"pi30 = R(pi) ; print pi30"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Με log(10,2)
υπολογίζουμε τον λογάριθμο του 10 με βάση το 2, γιατί το όρισμα στην RealField
\n",
"εκφράζεται σε bits
, και για κάθε δεκαδικό ψηφίο χρειαζόμαστε $\\log_2 10\\approx 3.32$ bits. Μετά την δημιουργία του R
, μετατρέπουμε το σύμβολο για την μαθηματική σταθερή $\\pi$ σε μια προσέγγιση 30 ψηφίων, την οποία καταχωρούμε στην τιμή pi30
. Για να ελέγξουμε την διαφορά του $\\pi$ και του pi30
με την δεδομένη ακρίβεια των 30 ψηφίων δίνουμε\n",
""
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.00000000000000000000000000000\n"
]
}
],
"source": [
"print R(pi-pi30)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.69568553528388823010177990083205496387e-31\n"
]
}
],
"source": [
"print RealField(40*log(10,2))(pi-pi30)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"οπότε η τιμή pi30
έχει\n",
"την επιθυμητή ακρίβεια 30 δεκαδικών ψηφίων. Για να πάρουμε βοήθεια για κάποια συνάρτηση/εντολή του Sage εκτελούμε για παράδειγμα "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on built-in function RealField in module sage.rings.real_mpfr:\n",
"\n",
"RealField(...)\n",
" RealField(int prec=53, int sci_not=0, rnd=MPFR_RNDN)\n",
" File: sage/rings/real_mpfr.pyx (starting at line 360)\n",
" \n",
" RealField(prec, sci_not, rnd):\n",
" \n",
" INPUT:\n",
" \n",
" - ``prec`` -- (integer) precision; default = 53 prec is\n",
" the number of bits used to represent the mantissa of a\n",
" floating-point number. The precision can be any integer between\n",
" :func:`mpfr_prec_min()` and :func:`mpfr_prec_max()`. In the current\n",
" implementation, :func:`mpfr_prec_min()` is equal to 2.\n",
" \n",
" - ``sci_not`` -- (default: ``False``) if ``True``, always display using\n",
" scientific notation; if ``False``, display using scientific notation\n",
" only for very large or very small numbers\n",
" \n",
" - ``rnd`` -- (string) the rounding mode:\n",
" \n",
" - ``'RNDN'`` -- (default) round to nearest (ties go to the even\n",
" number): Knuth says this is the best choice to prevent \"floating\n",
" point drift\"\n",
" - ``'RNDD'`` -- round towards minus infinity\n",
" - ``'RNDZ'`` -- round towards zero\n",
" - ``'RNDU'`` -- round towards plus infinity\n",
" - ``'RNDA'`` -- round away from zero\n",
" - for specialized applications, the rounding mode can also be\n",
" given as an integer value of type ``mpfr_rnd_t``. However, the\n",
" exact values are unspecified.\n",
" \n",
" EXAMPLES::\n",
" \n",
" sage: RealField(10)\n",
" Real Field with 10 bits of precision\n",
" sage: RealField()\n",
" Real Field with 53 bits of precision\n",
" sage: RealField(100000)\n",
" Real Field with 100000 bits of precision\n",
" \n",
" Here we show the effect of rounding::\n",
" \n",
" sage: R17d = RealField(17,rnd='RNDD')\n",
" sage: a = R17d(1)/R17d(3); a.exact_rational()\n",
" 87381/262144\n",
" sage: R17u = RealField(17,rnd='RNDU')\n",
" sage: a = R17u(1)/R17u(3); a.exact_rational()\n",
" 43691/131072\n",
" \n",
" .. NOTE::\n",
" \n",
" The default precision is 53, since according to the MPFR\n",
" manual: 'mpfr should be able to exactly reproduce all\n",
" computations with double-precision machine floating-point\n",
" numbers (double type in C), except the default exponent range\n",
" is much wider and subnormal numbers are not implemented.'\n",
"\n"
]
}
],
"source": [
"help(RealField)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"ή εναλλακτικά\n",
""
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"RealField?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Η τελευταία εντολή μας ανοίγει αυτόματα μια νέα υποσελίδα στο κάτω μέρος της web-σελίδας που δουλεύουμε, στην οποία εμφανίζεται το κείμενο με την βοήθεια. \n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Ένας εναλλακτικός τρόπος αριθμητικής προσέγγισης οποιουδέποτε πραγματικού αριθμού είναι με την χρήση απλών συνεχών κλασμάτων. Ένα απλό συνεχές κλάσμα ορίζεται από μια λίστα $[b_0;b_1,b_2,b_3,\\ldots]$, όπου $b_i$, $i=1,2\\ldots$ είναι θετικοί ακέραιοι και μόνο ο $b_0$ μπορεί να είναι μή-θετικός ακέραιος. Κάθε πραγματικός αριθμός $x$ (ρητός, άρρητος ή υπερβατικός) έχει την αναπαράσταση \n",
"$$x = b_0 + \\frac{1}{ b_1 + \\frac{1}{ b_2 + \\frac{1}{ b_3 + \\cdots}} } \\,. $$\n",
"Οι ρητοί αριθμοί που προκύπτουν κρατώντας μόνο ένα πεπερασμένο πλήθος όρων στο συνεχές κλάσμα λέγονται συγκλίνοντες.\n",
"Για παράδειγμα "
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1; 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...]\n"
]
}
],
"source": [
"x = sqrt(2)\n",
"c = continued_fraction(x); print c"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Δηλαδή\n",
"$$\\sqrt{2} = 1 + \\frac{1}{ 2 + \\frac{1}{ 2 + \\frac{1}{ 2 + \\cdots}} } \\,. $$\n",
"και οι συγκλίνοντες είναι \n",
"$$ 1 \\,,\\quad \\frac{3}{2} = 1+ \\frac{1}{2}\\,,\\quad \\frac{7}{5} = 1+ \\frac{1}{2+\\frac{1}{2}} \\,,\\cdots$$\n",
"Στο Sage εκτελούμε\n",
""
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lazy list [1, 3/2, 7/5, ...]\n"
]
}
],
"source": [
"print c.convergents()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"665857/470832\n"
]
}
],
"source": [
"print c.convergent(15)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"44302225809207714047802677511548402965313235415702533504483\n"
]
}
],
"source": [
"print c.numerator(153)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"31326404291348457390865124320006534354088526499185529979738\n"
]
}
],
"source": [
"print c.denominator(153)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"όπου οι συναρτήσεις numerator(n)
, και denominator(n)
μας δίνουν τον αριθμητή και τον παρονομαστή του $n$-στού συγκλίνοντα στην αναπαράσταση του πραγματικού $x$ με απλά συνεχή κλάσματα.\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.6 Μιγαδικοί, αλγεβρικοί αριθμοί και πεπερασμένα σώματα"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.6.1 Μιγαδικοί αριθμοί"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Στο Sage το σώμα των μιγαδικών αριθμών είναι γνωστό ως ComplexField()
, όπου στο όρισμα μπορούμε να θέσουμε (σε bits) την ακρίβεια που θέλουμε να χρησιμοποιήσουμε στους υπολογισμούς. Όμως, δεν πρέπει να μας διαφεύγει ότι το βασικό χαρακτηριστικό του Sage είναι ότι πρόκειται για ένα λογισμικό που εκτελεί συμβολικούς υπολογισμούς. Στο Sage η φανταστική μονάδα δηλώνεται με I
.\n",
""
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Complex Field with 100 bits of precision\n"
]
}
],
"source": [
"C = ComplexField(100); print C"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"I\n"
]
}
],
"source": [
"print sqrt(-1)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-1\n"
]
}
],
"source": [
"print I^2"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = (-1+I)^2; b = (1 - I)^2;"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-2*I\n"
]
}
],
"source": [
"print a"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-2*I\n"
]
}
],
"source": [
"print b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Το Sage γνωρίζει να λύνει πολυωνυμικές εξισώσεις με συντελεστές στους μιγαδικούς αριθμούς. Για παράδειγμα θα λύσουμε την εξίσωση \n",
"$$ z^3=i$$\n",
"Ορίζουμε με την συνάρτηση var
μια (συμβολική έκφραση) μεταβλητή $z$ και με την εντολή solve
λύνουμε την παραπάνω εξίσωση. Χρησιμοποιούμε το προαιρετικό όρισμα solution_dict=True
για να πούμε στην συνάρτηση solve
να μας επιστρέψει τις λύσεις στην μορφή μιας λίστας Python
με ανάλογο λεξικό. "
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[{z: 1/2*I*sqrt(3)*(-1)^(1/6) - 1/2*(-1)^(1/6)}, {z: -1/2*I*sqrt(3)*(-1)^(1/6) - 1/2*(-1)^(1/6)}, {z: (-1)^(1/6)}]\n",
"lyseis
. Με τον ίδιο τρόπο δημιουργούμε τις λίστες metra
, gwnies
, που περιέχουν τα μέτρα και τις γωνίες των λύσεων, αντίστοιχα. Στο Sage το πραγματικό και το φανταστικό μέρος ενός μιγαδικού αριθμού δίνονται με τις συναρτήσεις \n",
"real_part()
και imag_part()
, αντίστοιχα.
\n",
"Οι εντολές abs()
και arg()
, μας δίνουν το μέτρο και το όρισμα (argument) ενός μιγαδικού αριθμού, αντίστοιχα."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"lyseis=[];shmeia=[];metra=[];gwnies=[];\n",
"for i in [0..(len(rizes)-1)]: \n",
" lyseis.append( real_part( rizes[i][z] ) + I*imag_part( rizes[i][z]) )\n",
" metra.append( abs( rizes[i][z] ).simplify() )\n",
" gwnies.append( arg( rizes[i][z] ).simplify() )"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[-1/2*sqrt(3) + 1/2*I, -I, 1/2*sqrt(3) + 1/2*I]\n"
]
}
],
"source": [
"print lyseis"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 1, 1]\n"
]
}
],
"source": [
"print metra"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[5/6*pi, -1/2*pi, 1/6*pi]\n"
]
}
],
"source": [
"print gwnies"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Παρατηρούμε ότι και οι τρείς λύσεις έχουν μέτρο μονάδα, συνεπώς βρίσκονται πάνω στον μοναδιαίο κύκλο, και σε γωνίες \n",
"$$ \\frac{5\\,\\pi}{6} \\,,\\quad -\\frac{\\pi}{2} \\,,\\quad \\frac{\\pi}{6}\\,. $$\n",
"αντίστοιχα."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Τέλος, απεικονίζουμε γραφικά τα αποτελέσματά μας στο μιγαδικό επίπεδο.\n",
"Οι αντίστοιχες εντολές για γραφικές παραστάσεις σε δυο και τρεις διαστάσεις θα μας απασχολήσουν εκτενέστερα σε άλλη ενότητα. Προς το παρόν δώστε μεγαλύτερη έμφαση στο γεγονός ότι το Sage μας πληροφορεί ότι οι λύσεις της εξίσωσης $$z^3=i $$ είναι το σύνολο των μιγαδικών αριθμών\n",
"\n",
"$$ \\left\\lbrace \\frac{\\sqrt{3}}{2} + \\frac{i}{2} \\,, \\quad -\\frac{\\sqrt{3}}{2} + \\frac{i}{2} \\,,\\quad\n",
"-i\\right\\rbrace\\,. $$"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "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\nxphs/X8vDgPHFW91VQAAAABJRU5ErkJggg==\n",
"text/plain": [
"Graphics object consisting of 4 graphics primitives"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"var(\"x y\")\n",
"kyklos=implicit_plot(x^2+y^2==1,(x,-1,1),(y,-1,1))\n",
"pp=sum([point( ( (real_part( rizes[i][z]) , imag_part( rizes[i][z])) ), \n",
" color=rainbow(3)[i] , size=50) for i in [0..(len(rizes)-1)]])\n",
"show(kyklos+pp,figsize=4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.6.2 Αλγεβρικοί αριθμοί"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
" \n",
"Ο πραγματικός αριθμός $\\sqrt{2}$ είναι ένας αλγεβρικός αριθμός. Το ελάχιστο πολυώνυμο που έχει ρίζα έναν αλγεβρικό αριθμό, λέγεται το ελάχιστο πολυώνυμο του αριθμού. Για παράδειγμα, \n",
"η εντολή\n",
""
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x^2 - 2\n"
]
}
],
"source": [
"print sqrt(2).minpoly()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"μας επιστρέφει ότι το ελάχιστο πολυώνυμο του $\\sqrt{2}$ είναι το $x^2-2$. Το αποτέλεσμα της παραγοντοποίησης ενός πολυωνύμου εξαρτάται από το σώμα των αριθμών που είναι ορισμένο. \n",
""
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(x + 1)*(x - 1)\n"
]
}
],
"source": [
"print factor(x^2-1)"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x^2 - 2\n"
]
}
],
"source": [
"print factor(x^2-2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" \n",
"Το πολυώνυμο $x^2-1$ παραγοντοποιείται σε $(x+1)(x-1)$, ενώ το πολυώνυμο $x^2-2$ δεν παραγοντοποιείται πάνω στο προεπιλεγμένο σώμα, που είναι το σύνολο $\\mathbb{Q}$ των ρητών. Αν ένα πολυώνυμο δεν παραγοντοποιείται σε ένα συγκεκριμένο σώμα λέγεται ανάγωγο στο αντίστοιχο σώμα. Μπορούμε να ορίσουμε ένα σώμα $K$ στο οποίο το $c$ είναι η τετραγωνική ρίζα του $2$, και να υπολογίζουμε και να απλοποιούμε εκφράσεις στο K, έχοντας ενσωματώσει την πληροφορία ότι το ελάχιστο πολυώνυμο του $\\sqrt{2}$ είναι το $x^2-2$. \n",
""
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number Field in c with defining polynomial x^2 - 2\n"
]
}
],
"source": [
"K.
\n",
"\n",
"
\n",
"Παίρνοντας πολυωνυμικές κλάσεις ισοϋπόλοιπων $\\mod f(x)$, τα στοιχεία του $\\mathbb{F}_{3^2}$ αντιστοιχούν στα $3^2$ το πλήθος πολυώνυμα πρώτου βαθμού, $g(x)=a_1\\,x+a_0$, με $a_0,a_1 \\in \\mathbb{F}_{3}$. \n",
"GF
(Galois Field) όπου σαν ορίσματα δίνουμε το πλήθος των στοιχείων του $\\mathbb{F}_{3^2}$, το όνομα της πρωταρχικής ρίζας του πολυωνύμου $f(x)$, και τέλος το ανάγωγο πολυώνυμο $f(x)$ με συντελεστές στον $\\mathbb{Z}_3$, το οποίο στο συγκεκριμένο παράδειγμα είναι το $f(x)=x^2+x+2$.
\n",
"\n",
"Για αναφορά, καταχωρούμε ξεχωριστά σε ένα πίνακα με ένα και μόνο στοιχείο που δηλώνει ότι υπολογίζουμε το γινόμενο $x \\, y$ των στοιχείων του F
"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[x*y]\n"
]
}
],
"source": [
"x , y = var('x, y')\n",
"prod = matrix([ x*y ]); print prod"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Με ένα διπλό loop
υπολογίζουμε τα γινόμενα x*y
, καθώς τα x
και y
διατρέχουν τα μη μηδενικά στοιχεία του σώματος F
, και τα καταχωρούμε σ' ένα τετραγωνικό πίνακα 8x8
ως εξής\n",
""
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2*a + 1 2*a + 2 2 2*a a + 2 a + 1 1 a]\n",
"[2*a + 2 2 2*a a + 2 a + 1 1 a 2*a + 1]\n",
"[ 2 2*a a + 2 a + 1 1 a 2*a + 1 2*a + 2]\n",
"[ 2*a a + 2 a + 1 1 a 2*a + 1 2*a + 2 2]\n",
"[ a + 2 a + 1 1 a 2*a + 1 2*a + 2 2 2*a]\n",
"[ a + 1 1 a 2*a + 1 2*a + 2 2 2*a a + 2]\n",
"[ 1 a 2*a + 1 2*a + 2 2 2*a a + 2 a + 1]\n",
"[ a 2*a + 1 2*a + 2 2 2*a a + 2 a + 1 1]\n"
]
}
],
"source": [
"MultTable = matrix( [ [x*y for x in F.list()[1:9] ] for y in F.list()[1:9] ] ); print MultTable"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Τέλος, διαμορφώνουμε ένα πίνακα κατά blocks
που μας δίνει έναν εύχρηστο τρόπο για να χρησιμοποιούμε τον πίνακα πολλαπλασιασμού του σώματος F.\n",
""
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ x*y| a 2*a + 1 2*a + 2 2 2*a a + 2 a + 1 1]\n",
"[-------+---------------------------------------------------------------]\n",
"[ a|2*a + 1 2*a + 2 2 2*a a + 2 a + 1 1 a]\n",
"[2*a + 1|2*a + 2 2 2*a a + 2 a + 1 1 a 2*a + 1]\n",
"[2*a + 2| 2 2*a a + 2 a + 1 1 a 2*a + 1 2*a + 2]\n",
"[ 2| 2*a a + 2 a + 1 1 a 2*a + 1 2*a + 2 2]\n",
"[ 2*a| a + 2 a + 1 1 a 2*a + 1 2*a + 2 2 2*a]\n",
"[ a + 2| a + 1 1 a 2*a + 1 2*a + 2 2 2*a a + 2]\n",
"[ a + 1| 1 a 2*a + 1 2*a + 2 2 2*a a + 2 a + 1]\n",
"[ 1| a 2*a + 1 2*a + 2 2 2*a a + 2 a + 1 1]\n"
]
}
],
"source": [
"groupF = block_matrix([[prod, multgroupF],[multgroupF.transpose(), MultTable]]) ; print groupF"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Στην αριστερή στήλη και την πρώτη γραμμή αναφέρονται τα στοιχεία της πολλαπλασιαστικής ομάδας του F. Το στοιχείο που είναι στην $(i,j)$ θέση, του μεγάλου 8x8
τετραγωνικού block
πίνακα, αναφέρεται στο γινόμενο του στοιχείου που είναι στην $i$ θέση στην αριστερή στήλη, με εκείνο που είναι στην $j$ θέση στην πάνω γραμμή. Αυτός είναι ο πίνακας της πολλαπλασιαστικής ομάδας του πεπερασμένου σώματος $\\mathbb{F}_{3^2}[x]\\,/\\,f(x)$.
\n",
"Παρατηρώντας τις μονάδες που εμφανίζονται στην αντιδιαγώνιο, διαπιστώνουμε εύκολα ότι, για παράδειγμα, τα στοιχεία $2\\,a+2=a^3$ και $2\\,a=a^5$, είναι το ένα πολλαπλασιαστικό αντίστροφο του άλλου, καθώς και ότι το $2=a^4$ είναι πολλαπλασιαστικό αντίστροφο του εαυτού του, αφού $2\\cdot 2 = 4 = 1 \\mod 3$. Πράγματι στο Sage ελέγχουμε \n",
""
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print (2*a+2)*(2*a)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print a^3*a^5"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print a^4*a^4"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n"
]
}
],
"source": [
"print Mod(2*2,3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Μπορούμε να παραγοντοποιήσουμε και να αναπτύξουμε πολυώνυμα πάνω σε πεπερασμένα σώματα. Δημιουργούμε ένα δακτύλιο πολυωνύμων με μεταβλητή x
και συντελεστές πάνω στο πεπερασμένο σώμα που κατασκευάσαμε παραπάνω ως εξής\n",
""
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Univariate Polynomial Ring in x over Finite Field in a of size 3^2\n"
]
}
],
"source": [
"R.var
. Σε προηγούμενα παραδείγματα είχαμε χρησιμοποιήσει την συνάρτηση αυτή ώς εξής var('x')
. type
). Βάζοντας εισαγωγικά ('
ή \"
) γύρω από τα ονόματα των μεταβλητών αποτρέπουμε στο να δοθεί στην μεταβλητή μια συγκεκριμένη τιμή.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.7.1 Εκφράσεις και ονόματα\n",
"\n",
"pi
. \n",
"Μπορούμε να εργαζόμαστε με το pi
ως συμβολική μεταβλητή και να του δίνουμε οποιαδήποτε τιμή.\n",
"\n",
"pi
είναι μια συμβολική έκφραση. Ας του θέσουμε μια τιμή να δούμε τι θα συμβεί.\n",
""
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.14000000000000 pi
έπαψε να είναι συμβολική έκφραση και το Sage μας πληροφορεί ότι απέκτησε τύπο sage.rings.real_mpfr.RealLiteral
. Δηλαδή την χάσαμε την τιμή του pi
ως μαθηματική σταθερή;
\n",
"\n",
"Με την εντολή restore
μπορούμε να ανακτήσουμε τον τύπο του pi
ως συμβολική έκφραση καθώς και την τιμή του "
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pi restore
. Μετά από την εκτέλεση της εντολής restore
διαπιστώνουμε ότι το pi
ανακτά και πάλι την ιδιότητά του ως έκφραση, και φυσικά την τιμή του με την ακρίβεια που περιγράψαμε στα προηγούμενα.
\n",
"\n",
"Μια τιμή μπορεί να καταχωρηθεί ως ένα string
, η οποία μπορεί να υπολογισθεί αργότερα με την εντολή eval
"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3.14000000000000 x 3.14000000000000\n"
]
}
],
"source": [
"x = 3.14\n",
"timh = 'x'\n",
"print x , timh, eval(timh)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.7.2 Επαλήθευση λύσεων\n",
"\n",
"solve
θα πάρουμε μια λίστα από εκφράσεις. solution_dict=True
\n",
"z
, σε μια άλλη έκφραση, όπως για παράδειγμα στην ίδια εξίσωση για να επαληθεύσουμε ότι είναι πράγματι λύση της. Αυτό επιτυγχάνεται με την εντολή substitute()
\n",
"keys()
ανακτούμε την τιμή της μεταβλητής z, πριν της δώσουμε την τιμή 3. Επιπλέον παρατηρούμε ότι η εντολή αντικατάστασης substitute
εξακολουθεί να δουλεύει :\n",
"sols
. Για να πληροφορηθούμε για την τρέχουσα τιμή που αναφέρεται η μεταβλητή z, εκτελούμε την εντολή reset()
\n",
"Υπενθυμίζουμε ότι η Python μας επιτρέπει να θέτουμε τιμές ταυτόχρονα ως εξής:\n",
"
\n",
"Μια συμβολική έκφραση υπολογίζεται για συγκεκριμένες τιμές των συμβολικών μεταβλητών της, με την παρακάτω εντολή reset()
, και τρέχουμε eval()
. Η εντολή αυτή δέχεται ως όρισμα ένα string
. Με διαδοχικές χρήσεις της eval()
μπορούμε να φτάσουμε από το x μέχρι το 3eval()
μας δίνει z, ενώ η δεύτερη και η τρίτη εφαρμογή της μας δίνει 3. Παρατηρήστε ότι η σειρά που γίνεται η ανάθεση τιμών σε μεταβλητές παρουσιάζει διαφοροποιήσεις. lists
, dictionaries
και tuples
.
\n",
"\n",
"Οι κύριοι τύποι αριθμών στο Sage είναι οι ακέραιοι, οι ρητοί, οι πραγματικοί κι οι μιγαδικοί και έχουν τις συντομεύσεις ZZ, QQ, RR
και CC
, αντίστοιχα. Στην παράγραφο αυτή θα δούμε πως μπορούμε να περιορίζουμε τον τύπο ενός αριθμού, και πως μπορούμε να διαλέξουμε έναν τυχαίο αριθμό το οποίο είναι αρκετά χρήσιμο. Επίσης θα δούμε πως μπορούμε να επιλέξουμε κάποιο από τα δυο μέλη μιας εξίσωσης. \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.8.1 Περιορισμός στους βασικούς τύπους αριθμών\n",
"\n",
"ZZ, QQ, RR
και CC
, αντίστοιχα. "
]
},
{
"cell_type": "code",
"execution_count": 97,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Integer Ring\n"
]
}
],
"source": [
"print ZZ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"QQ
, δηλαδή το σώμα των ρητών αριθμών\n",
"QQ(RR(y))
. Η διαφοροποίηση οφείλεται στο ότι η ακρίβεια του RR
είναι η ίδια με αυτή των 53 bits (αποθηκεύονται 52) ενός επεξεργαστή που εκτελεί πράξεις διπλής κινητής υποδιαστολής.\n",
"RR
έχει ακρίβεια 53 bits, η τελευταία δεν είναι η ίδια με αυτή του RealDoubleField
(RDF
). Η διαφορά αυτή γίνεται αντιληπτή γεννώντας\n",
"έναν τυχαίο αριθμό στα σώματα RR
και RDF
αντίστοιχα\n",
"sage.rings.real_mpfr.RealNumber
, ενώ του y είναι\n",
"sage.rings.real_double.RealDoubleElement
. Η ίδια διαφορά διατηρείται και για τους μιγαδικούς \n",
"sage.symbolic.expression.Expression
, δηλαδή μια συμβολική έκφραση. Η έκφραση που δηλώσαμε με eqn
έχει έναν χειριστή (operator
)\n",
"lhs()
, είναι η left()
και \n",
"left_hand_side()
, ενώ της εντολής rhs()
, είναι οι right()
και right_hand_side()
, αντίστοιχα.\n",
"functions
). Για παράδειγμα:\n",
"our_append
) που ορίσαμε, ας την τροποποιήσουμε ελαφρώς, με την our_append2
), στην οποία \n",
"τυπώνουμε επιπλέον την ταυτότητα του L \n",
"our_append2
δημιουργήθηκε μια άδεια λίστα L = [ ], η οποία τοποθετήθηκε κάπου στην μνήμη. Κάθε φορά που καλείται η συνάρτηση με κάποιο όρισμα, το Sage ανατρέχει στην L, στην ίδια διεύθυνση στην μνήμη. Παρατηρήστε ότι η L δεν υπάρχει έξω από την συνάρτηση!\n",
"ctypes
μπορούμε να ανακτούμε την διεύθυνση στην οποία είναι τοποθετημένο ένα αντικείμενο\n",
"fast_callable
\n",
"add\n",
" |\n",
" +-- sub\n",
" | |\n",
" | +-- add\n",
" | | |\n",
" | | +-- ipow\n",
" | | | |\n",
" | | | +-- v_0\n",
" | | | |\n",
" | | | +-- 3\n",
" | | |\n",
" | | +-- mul\n",
" | | |\n",
" | | +-- mul\n",
" | | | |\n",
" | | | +-- 4\n",
" | | | |\n",
" | | | +-- v_0\n",
" | | |\n",
" | | +-- ipow\n",
" | | |\n",
" | | +-- v_1\n",
" | | |\n",
" | | +-- 2\n",
" | |\n",
" | +-- mul\n",
" | |\n",
" | +-- 7\n",
" | |\n",
" | +-- v_1\n",
" |\n",
" +-- 2\n",
"