{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# A Brief Introduction to Sage Math\n", "\n", "This document aims to give a crash-course to Sage. There are many additional resources for help, including the built-in documentation (discussed below), the [**official Sage tutorial**](https://doc.sagemath.org/html/en/tutorial/index.html), and the (highly recommended) open textbook [**Computational Mathematics with SageMath**](http://sagebook.gforge.inria.fr/english.html).\n", "\n", "Sage is free and open source. Information on running a local installation can be found on the [**Sage installation guide**](https://doc.sagemath.org/html/en/installation/index.html). Alternatively, Sage can be run \"in the cloud\" by making a (free) account on the [**CoCalc website**](cocalc.com) or by uploading a Jupyter notebook to a public git repository and using [**mybinder.org**](https://mybinder.org).\n", "\n", "This document is written as a **Jupyer notebook**, the most common (and convenient) way to write and execute Sage code. A notebook is composed of *cells*. Most of the cells in this notebook consist of an Input section (containing Sage code) and (potentially) an output section (containing the result of evaluating that Sage code) $-$ some code cells simply perform a computation without returning anything (for instance, updating the values of variables). A few cells (including the current one) consist of formatted text and LaTeX equations, written using the Markdown markup language. A third type of cell contains plain, unformatted text.\n", "\n", "**To execute a piece of Sage code, click on the Input section of the corresponding code cell and hit Shift + Enter (only hitting Enter simply adds a new line). The reader should execute each statement as they work through the notebook, and is encouraged to modify the code and play around as they go. Note that skipping a cell may result in errors when later cells are executed (for instance, if one skips a code block defining a variable and later tries to run code calling that variable). There are a selection of short exercises throughout, and a few larger exercises in the final section.** To add a new cell, click to the left of any cell and press the \"a\" key. To delete a cell, click to the left of a cell and press the \"d\" key. These (and other) tasks can also be accomplished through the menu bars at the top of the page." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 1: The Basics of Sage\n", "\n", "We begin with an explanation of arithmetic in Sage, if statements, for and while loops, and Sage functions (in the programming sense; symbolic mathematical functions are described in Part 2 below)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "13" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Any text on a line after a '#' symbol is considered a comment, and is not evaluated by Sage\n", "# Sage can be used as a calculator using usual math notation \n", "# (recall you need to click on a cell and hit Shift + Enter to evaluate it)\n", "1 + 3*4" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Code in a Sage cell should be entered in sequence, with one \"instruction\" per line\n", "# (multiple instructions can be put on the same line using a semicolon -- see examples below)\n", "# The result of previous executions of Sage cells (both the current cell and other cells) is stored by Sage\n", "# All (non-commented) code is executed, however only the output of the final line is printed by default\n", "1 + 2\n", "2 ^ 3" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "8\n", "1/2\n", "0.500000000000000\n", "2\n" ] } ], "source": [ "# To print other lines, use the print command\n", "print(2^3) # This is an integer\n", "print(5/10) # This is an exact rational number\n", "print(5.0/10) # This is a floating point number\n", "print(11 % 3) # This is 11 mod 3" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n" ] }, { "data": { "text/plain": [ "15" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Multiple instructions can be put on the same line using a semicolon\n", "# Again, only the output of the final line is displayed by default\n", "2+2\n", "print(1+2); 3*5" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{1}{\\pi} + \\frac{1}{2}\n", "\\end{math}" ], "text/plain": [ "1/pi + 1/2" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{1}{2} \\, \\sqrt{3}\n", "\\end{math}" ], "text/plain": [ "1/2*sqrt(3)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\log\\left(2\\right)\n", "\\end{math}" ], "text/plain": [ "log(2)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}0.693147180559945\n", "\\end{math}" ], "text/plain": [ "0.693147180559945" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{1}{2} i \\, \\sqrt{3} - \\frac{1}{2}\n", "\\end{math}" ], "text/plain": [ "1/2*I*sqrt(3) - 1/2" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}e^{\\left(\\frac{2}{101} i \\, \\pi\\right)}\n", "\\end{math}" ], "text/plain": [ "e^(2/101*I*pi)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The \"show\" command outputs a latex-like pretty output\n", "# Sage knows common math constants such as pi (lower case), e, and I (or the alternative i)\n", "# Most common mathematical functions are supported by default\n", "show(5/10 + 1/pi)\n", "show(sin(pi/3))\n", "show(log(2))\n", "show(log(2).n()) # Adding \".n()\" gives a numerical approximation (can use \".n(k)\" to get k bits)\n", "show(exp(i*2*pi/3))\n", "show(exp(I*2*pi/101))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The area of a circle of radius 1 is approximately 3.14159265358979\n", "The square-root of log(2) is approximately 0.832554611157698\n" ] } ], "source": [ "# Mathematical objects and variables can be inserted in print commands using commas, \n", "# or using empty curly braces {} and .format(math1,math2,...)\n", "print(\"The area of a circle of radius 1 is approximately\",pi.n())\n", "print(\"The square-root of {} is approximately {}\".format(log(2),sqrt(log(2)).n()))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function print in module builtins:\n", "\n", "print(...)\n", " print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n", " \n", " Prints the values to a stream, or to sys.stdout by default.\n", " Optional keyword arguments:\n", " file: a file-like object (stream); defaults to the current sys.stdout.\n", " sep: string inserted between values, default a space.\n", " end: string appended after the last value, default a newline.\n", " flush: whether to forcibly flush the stream.\n", "\n" ] } ], "source": [ "# To access the help page for a function, type the name of the function and then add a question mark\n", "# For instance, evaluating the expression \"sin?\" (without quotes) gives the help page for sine\n", "# THIS WILL OPEN A NEW WINDOW AREA\n", "# Using two question marks (e.g. \"sin??\") shows the source code of the function\n", "# (Note that for many low level functions like sin Sage relies on outside packages \n", "# and the source code is not very informative)\n", "\n", "# Similar information is provided by the \"help\" command, which prints below the current cell\n", "help(print)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "132" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Variables are defined using the \"=\" operator\n", "# Note that some operations (such as variable assignment) do not have an output\n", "# So we add another line to print the value of our variable\n", "mult = 11 * 12\n", "mult" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "132\n" ] } ], "source": [ "# The values \"_\", \"__\", and \"___\" (using one, two, and three underscores) \n", "# are the last three output values. Printing displays content but does *not* \n", "# return a value, so a block ending with a print statement has no output\n", "print(_)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "132" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The output of previous cells can be directly accessed using the syntax Out[k]\n", "# NOTE: cells are numbered by execution order -- running cells repeatedly or in \n", "# different orders will change their numbering!\n", "Out[8]" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Positive\n" ] } ], "source": [ "# Sage is built on Python, and uses much of the same syntax. \n", "# In particular, indentation is extremely important.\n", "# If statements are defined with indentation\n", "a = 2\n", "\n", "if a<0:\n", " print(\"Negative\")\n", "elif a==0:\n", " print(\"Zero\")\n", "else:\n", " print(\"Positive\")" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Positive\n" ] } ], "source": [ "# In addition, an if statement can be written in one line\n", "a = 2\n", "if a>0: print(\"Positive\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "24\n", "3628800\n", "\n" ] } ], "source": [ "# Functions are also defined with indentation\n", "def fact(n):\n", " if n==0:\n", " return 1;\n", " else:\n", " return n*fact(n-1)\n", "\n", "print(fact(4))\n", "print(fact(10))\n", "print(fact) # Prints reference to the function\n", "# fact?? # uncommenting and running this code displays the source code for the function fact" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "################################################\n", "# EXERCISE: Make a function to compute the nth Fibonacci number (defined by fib(n+2) = fib(n+1) + fib(n)\n", "# and fib(0)=fib(1)=1). What is the highest number you can compute in 5 seconds?\n", "#\n", "# Adding the line \"@cached_function\" directly before the function definition tells Sage to store the \n", "# result of each function return, which will speed up the computation. Add this line then see how high\n", "# you can go in 5 seconds.\n", "################################################\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4]\n", "4\n", "1\n", "2\n", "3\n", "[2, 3]\n", "[2, 3]\n", "[2, 3, 4]\n" ] } ], "source": [ "# Lists in Sage are defined with square brackets\n", "LST = [1,2,3,4]\n", "\n", "print(LST)\n", "print(len(LST)) # Print the length of the list\n", "print(LST[0]) # Access elements from the left (starting at index 0)\n", "print(LST[1]) # Print second element of the list\n", "print(LST[-2]) # Negative indices access elements from the right\n", "print(LST[1:3]) # Define sublist\n", "print(LST[1:-1]) # Define sublist using negative index\n", "print(LST[1:]) # Define sublist from a fixed index to end of list" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 'a', 'b', 'c']\n", "hello world\n" ] } ], "source": [ "# Lists can be concatenated with '+'\n", "# Strings can be concatenated similarly (they are lists of characters)\n", "print([1,2,3] + [\"a\",\"b\",\"c\"])\n", "print(\"hello\" + \" \" + \"world\")" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n", "25\n" ] } ], "source": [ "# For loops work over lists or generators, and are indented similarly to if statements and functions\n", "LST = [0,1,2,3,4,5]\n", "for k in LST:\n", " print(k^2)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n", "25\n" ] } ], "source": [ "# The notation a..b can be used to build the list of numbers between integers a and b\n", "for k in [0..5]:\n", " print(k^2)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "range(0, 5)\n", "[0, 1, 2, 3, 4]\n", "0\n", "1\n", "4\n", "9\n", "16\n" ] } ], "source": [ "# As in Python, Sage contains the function range(k), which encodes the numbers 0,1,...,k-1\n", "# In Sage versions 8.x and lower, which rely on Python 2, range(k) returns the list [0,1,...,k-1]\n", "# In Sage 9.0 and higher, which use Python 3, range(k) returns an *iterator* that can be converted to a list\n", "# (think of an iterator as a method to construct elements of a list, one by one, which can be more efficient)\n", "# We assume in our discussions that the user of this document is using Sage 9.0 or higher\n", "# More details on this change can be found here: https://docs.python.org/3.0/whatsnew/3.0.html#views-and-iterators-instead-of-lists\n", "\n", "print(range(5)) # printing an iterator just returns the iterator\n", "print(list(range(5))) # the iterator can be converted to a regular list\n", "for k in range(5): # loops can range directly over iterators, which can be more efficient\n", " print(k^2)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n" ] } ], "source": [ "# For loops can also be defined over one line\n", "for k in range(5): print(k^2)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 4, 9, 16]\n", "[-1, 1, -1, 1, -1]\n" ] } ], "source": [ "# There is a powerful alternate syntax for building lists using a \n", "# function f(x) on the elements of a list LST: [f(k) for k in LST]\n", "print([k^2 for k in range(5)])\n", "print([cos(k*pi) for k in [1..5]])" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "################################################\n", "# EXERCISE: Compute the sum of the first 100 perfect squares. \n", "# (Use the add function -- type \"add?\" or \"help(add)\" for its documentation)\n", "################################################\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n" ] } ], "source": [ "# While loops are defined similarly to for loops\n", "k = 0\n", "while k<5:\n", " print(k^2)\n", " k = k+1" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n", "16\n" ] } ], "source": [ "# While loops can be broken using 'break'\n", "k = 0\n", "while True:\n", " if k>= 5:\n", " break\n", " print(k^2)\n", " k = k+1" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The map operator applies a function to each element of a list \n", "# Similar to range, in Sage 9.0+ map returns a \"map object\" / iterator\n", "# The list command can be used to obtain an honest list from a map object\n", "list(map(abs,[-1,2,-3,4]))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[-2, 4, -6, 8]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# User defined functions can also be mapped, where appropriate\n", "def myfun(k):\n", " return 2*k\n", "\n", "list(map(myfun,[-1,2,-3,4]))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 4, 9, 16]\n", " at 0x245b4ed30>\n" ] } ], "source": [ "# Can also use map with 'lambda expressions' to define a function in place\n", "print(list(map(lambda t: t^2, [-1,2,-3,4])))\n", "print(lambda t: t^2) # Defines the function f(x) = x^2 in place" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[2, 4]\n" ] } ], "source": [ "# Can filter a list using 'filter'\n", "# Similar to range and map, in Sage 9.0+ filter returns a \"filter object\" / iterator\n", "# The list function can be applied to obtain an honest list from a filter object\n", "\n", "print(filter(lambda t: t>0, [-1,2,-3,4]))\n", "print(list(filter(lambda t: t>0, [-1,2,-3,4])))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[4, 9, 25, 49]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Can also use the list 'comprehension form' to filter elements when building a list\n", "[p^2 for p in [1..10] if is_prime(p)]" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 6, 7]\n", "['a', 'ab', 'abc', 'acb']\n" ] } ], "source": [ "# Can sort lists, when appropriate.\n", "# Sort is a function of a list (see Part 2 below for additional details)\n", "L = [1,4,3,2,7,6]\n", "L.sort() # Modifies the list L in place\n", "print(L)\n", "L = [\"a\",\"acb\",\"abc\",\"ab\"]\n", "L.sort() # Sort in lexicographical order\n", "print(L)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-1, 2, 3]\n", "[-1, 2, 3]\n", "[1, 2, 3]\n" ] } ], "source": [ "# Lists are stored by reference. Simply writing L2 = L1, makes L1 and L2 point to the *same* list\n", "# Use L2 = copy(L1) to make an independent copy\n", "# Note copy only works at one level of lists \n", "# (use the \"deepcopy\" command to copy a list of lists, and make everything independent)\n", "\n", "L1 = [1,2,3]\n", "L2 = L1 # L2 points to the same list as L1\n", "L3 = copy(L1) # L3 points to a new list, initialized with the same values as L1\n", "L2[0]=-1\n", "print(L1); print(L2); print(L3)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\verb|apple| : 1, \\verb|pear| : \\pi, \\verb|banana| : \\sin\\left(2\\right)\\right\\}\n", "\\end{math}" ], "text/plain": [ "{'apple': 1, 'pear': pi, 'banana': sin(2)}" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\pi + 1\n", "\\end{math}" ], "text/plain": [ "pi + 1" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left\\{\\verb|pear| : \\pi, \\verb|banana| : \\sin\\left(2\\right)\\right\\}\n", "\\end{math}" ], "text/plain": [ "{'pear': pi, 'banana': sin(2)}" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Sage also supports dictionaries, which for the user behave as lists indexed by strings\n", "L = {}; L['apple'] = 1; L['pear'] = pi; L['banana'] = sin(2)\n", "show(L)\n", "show(L['apple'] + L['pear'])\n", "del(L['apple'])\n", "show(L)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "###########################################################################\n", "# EXERCISE: Create a list containing the first 100 primes of the form 4*k+1\n", "###########################################################################\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 2: The Symbolic Ring and Sage Types\n", "\n", "We now see how to manipulate symbolic variables and abstract functions, including basic calculus operations and plotting, and how to determine the type and parent of an object." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "# Before running this section, we reset all variables\n", "reset()" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x^2 - 1\n" ] } ], "source": [ "# By default, when opening a notebook the variable \"x\" can be used to define a symbolic function / expression\n", "poly = x^2 - 1\n", "print(poly)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'y' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/Applications/SageMath-9.2.app/Contents/Resources/sage/local/lib/python3.8/site-packages/sage/all_cmdline.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Using any other (undeclared) variable will give an error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;31m# This behaviour can cause frustration for first-time Sage users\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mpoly2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'y' is not defined" ] } ], "source": [ "# Using any other (undeclared) variable will give an error\n", "# This behaviour can cause frustration for first-time Sage users\n", "poly2 = y^2 - 1" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x^2 - 1\n", "3\n" ] } ], "source": [ "# If the variable x is assigned a different value, this does not change the value of our symbolic expression!\n", "# Of course, any new symbolic expressions will use this updated value of x.\n", "x = 2\n", "print(poly)\n", "poly2 = x^2 - 1\n", "print(poly2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**MAKE SURE YOU UNDERSTAND THIS CRUCIAL POINT: \n", "This behaviour occurs because *Sage variables* (for instance, x on the left hand side of x = 2) are distinct from the underlying *symbolic variables* used to define symbolic expressions. By default the *Sage variable* x is initialized to a *symbolic variable* \"x\", and the expression poly above is defined in terms of this *symbolic variable*. Changing the *Sage variable* x to a new value does nothing to the underlying symbolic variable \"x\", which is why the value of poly does not change after setting x = 2.**" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "x\n" ] } ], "source": [ "# The easiest way to define a new symbolic variable having\n", "# the same name as a Sage variable is with the \"var\" command\n", "x = 2\n", "print(x) # Prints the value of the Sage variable x\n", "var('x') # Makes the Sage variable x point to the symbolic variable \"x\"\n", "print(x) # Prints the value of the Sage variable x, which is now the symbolic variable \"x\"" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(b*c + a)^2\n" ] } ], "source": [ "# Multiple variables can be defined at the same time\n", "var('a b c') # Initialize Sage variables a, b, and c to symbolic variables \"a\", \"b\", and \"c\"\n", "poly2 = (a + b*c)^2\n", "print(poly2)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "##############################################################################################################\n", "# EXERCISE: Guess the result of uncommenting and running the following code. Explain the output that does occur.\n", "##############################################################################################################\n", "# var('p q r'); r = q; q = p; p = r\n", "# print(p); print(q); print(r)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Symbolic Ring\n" ] } ], "source": [ "# The commands \"type\" and \"parent\" illustrate the domains in which Sage objects live.\n", "# Symbolic expressions, defined with symbolic variables, live in the Symbolic Ring.\n", "# Sage automatically determines where objects defined with \"=\" should live.\n", "# Part 3 below gives many more details about the types of objects in Sage, \n", "# and how to specify and manipulate them.\n", "var('a')\n", "poly = a\n", "print(type(poly))\n", "print(parent(poly))" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Integer Ring\n", "\n", "Rational Field\n", "\n", "Real Field with 53 bits of precision\n" ] } ], "source": [ "# Some additional examples\n", "poly = 10\n", "print(type(poly))\n", "print(parent(poly))\n", "print(type(1/2))\n", "print(parent(1/2))\n", "print(type(0.5))\n", "print(parent(0.5))" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "49\n", "\n", "\n" ] } ], "source": [ "# In Sage (as in Python) objects can have their own functions\n", "# Type \"poly2.\" (without quotes) then hit the *Tab* key to see the available functions for poly2\n", "# Run the command \"poly2.subs?\" to see the help page for the function poly2.subs\n", "# Run the command \"poly2.subs??\" to see the source code for the function poly2.subs\n", "var('a b c'); poly2 = (a + b*c)^2\n", "print(poly2.subs(a=1,b=2,c=3))\n", "print(poly2.subs)\n", "print(parent(poly2.subs))" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "##################################################################################################\n", "# EXERCISE: Uncomment and hit with the cursor on the far right of the following line see the\n", "# available functions for poly2 which begin with \"s\". Select one of the functions, look up its\n", "# documentation, then run the function (with appropriate arguments if necessary)\n", "##################################################################################################\n", "#poly2.s" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x + 1\n", "x + 1\n", "x^2 - 1\n", "(x + 1)*(x - 1)\n" ] } ], "source": [ "# Sage has many commands for manipulating expressions, such as simplify and expand.\n", "# Be careful -- in the Symbolic Ring, Sage simplifies without checking restrictions on variables\n", "var('x')\n", "print(((x-1)*(x+1)/(x-1)).simplify())\n", "print(simplify((x-1)*(x+1)/(x-1))) # simplify(p) is a built-in shortcut for type(p).simplify()\n", "print(expand((x-1)*(x+1)))\n", "\n", "pol = x^2-1\n", "print(pol.factor())" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x^3 == 1\n", "x^3\n", "\n" ] } ], "source": [ "# Equations are also symbolic expressions, defined using \"==\"\n", "eq1 = x^3 == 1\n", "print(eq1)\n", "print(eq1.lhs())\n", "print(type(eq1))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x = \\frac{1}{2} i \\, \\sqrt{3} - \\frac{1}{2}, x = -\\frac{1}{2} i \\, \\sqrt{3} - \\frac{1}{2}, x = 1\\right]\n", "\\end{math}" ], "text/plain": [ "[x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[x = \\frac{1}{2} i \\, \\sqrt{3} - \\frac{1}{2}, x = -\\frac{1}{2} i \\, \\sqrt{3} - \\frac{1}{2}, x = 1\\right]\n", "\\end{math}" ], "text/plain": [ "[x == 1/2*I*sqrt(3) - 1/2, x == -1/2*I*sqrt(3) - 1/2, x == 1]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The solve command works with equations\n", "show(solve(eq1,x))\n", "show(eq1.solve(x))" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2*cos(x) + sin(x)\n", "Symbolic Ring\n" ] } ], "source": [ "# Symbolic functions can be defined with symbolic variables\n", "var('x')\n", "f = sin(x)+2*cos(x)\n", "print(f)\n", "print(parent(f))" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x |--> 2*cos(x) + sin(x)\n", "Callable function ring with argument x\n" ] } ], "source": [ "# The syntax for a \"callable\" symbolic function is analogous\n", "var('x')\n", "f(x) = sin(x)+2*cos(x)\n", "print(f)\n", "print(parent(f))" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "8.31762924297529" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The find_root command can be used to approximate roots numerically\n", "# (additional details on finding roots of polynomials are given in the next section)\n", "f(x).find_root(-10, 10)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "Graphics object consisting of 1 graphics primitive" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Symbolic functions can be plotted with the plot command\n", "plot(f(x),x,0,10) # Syntax is \"plot(function, variable, xmin value, xmax value)\"" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkwAAAGECAYAAADEN3+HAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAA9hAAAPYQGoP6dpAABKQ0lEQVR4nO3deZzNdfvH8dfXmBnEjK2FSIposiRGEZE9laWiVKIFRYvSXaH1btHdr3S3DKFdiSJF9spWEYokSaVEKenmjNDYvr8/LkMxnGHOOZ+zvJ+Px/cxjHNmLsdx5n0+y/XxfN9HRERERA6ukOsCRERERKKdApOIiIhIEApMIiIiIkEoMImIiIgEocAkIiIiEoQCk4iIiEgQCkwiIiIiQcRdYPJMmud5nutaREREJD4Udl3AYQraZTMQCJCenk4gEIhEPSIiIhL7gg6yxN0Ik4iIiEioKTCJiIiIBKHAJCIiIhJEWAOT53nneJ430fO8XzzP8z3P65CP+zTxPO8zz/P+8jxvled514ezRhEREZFgwj3CdBTwBXBjfm7seV5lYDIwF6gDPAI87XnexWGrUERERCSIsO6S831/CjAFIJ+7/K8HfvJ9v++e33/teV494HZgXF53yMnJIScnZ+/vNy9fbr/497+heHEoXBiSk+1j0aKQnn7gVbIkpKWBOhGIRKVt2+B//4NAwK5Nm+xjdjbk5MCOHXZt377v1wCpqZCSsu/K/X3uS0HJknaVKQNly0IhLVIQkYOItrYCDYDp+31uGnCt53nJvn9gV4FBgwbxwAMP7P19rdxfvPUW7Nq179Vz507YutU+l5eiRaF8+byvk06Ck0+2V1SFKpGQysmBVavgu+/gxx/hl18OvDZtyvu+nmchKDn5wAssQG3fbt8j92MeLyOAhaVjjoFjj7XruOPgxBOhcmW7TjrJXg6SksLwIIhI1PPyCiFh+Uae5wMdfd9/5xC3WQm87Pv+I3/7XEPgY6C87/u/7H+f/UeYsrOzqVixIoFAgLS0tH/e2PctNGVn73urGgjAxo2wbl3er9SbN++7f4kSULUqZGTAaafZx4wMezXVq6jIIf3xByxdatc338C339r100/7QkxKSt7vWcqVs/crfx8UTk+3QeTDfQ+T+94pO3vfSNWGDfDrr/Dbb/s+rltnAW7dun33TU6GSpWgenWoUWPfVb26BTcRiVlBX0mibYQJDmxO6R3k8wCkpqaSmt9XKs+Do46yq1y5/N0nO9ve/n7/vV0rV8Ly5TBhgv0ZQLFicMYZkJm57zr5ZI1GScLasAHmz7fr888tJP38s/1Zaiqccoq997jsMqhSxX5dtar9twz3f5vChW0GPi0NKlQIfvtt2yw4/fCDXatWwYoV8PrrsGaN3SYpyeqvWXPfS0DduvYeS0TiQ7SNMM0BFvu+f8vfPtcReBMo5vv+9mDfJzs7e2+n7wNGmELJ920E6quv4IsvYNEiWLjQXlHB3gLXq2evnGefDY0b2yu0SJzZudMC0fz5MG+effzuO/uzY4+1/wK1a0OtWnZVqWKhJR4EAvYSsGyZXV98AZ99Blu2WPA79VQ480z773/OOTatp/dRIlEp6P/MaAtM/wEu9H0/42+fGwqc7vt+A/JxNErEAtPBbNiwLzzlXr/+am9B69eHZs3satgQihSJfH0iBbRzpz3FP/zQrnnzbIorORnq1IGzzoIGDexjpUqJFxB27YKvv7b/+gsW2OOzdKm9xypXzoLTOedA69Y2EC0iUcFtYPI8rzhQZc9vFwO3ATOB//m+/5PneYOA433fv2rP7SsDy4BhwAhsEfhzQBff98cRC4Fpf75vb7c/+MB+usycaaEqNdVGnnIDVP36WgclUevnn2HyZLs++MCW9pUoAU2a2NWwoYWlokVdVxqdNm2Cjz+GuXNhzhwLUzt32mjbeedBmzbQtKnN7ouIE84DU1MsIO3vFd/3u3ue9zJwou/7Tf92nybAk8BpwC/Af3zff27PH8deYNrf7t3w5Zf73p7Pnm0/fcqWhQsugPbtoWVLW2cl4siuXfDppzBpkoWkJUtsF1mDBvYDvkULW6MTL1NrkbZ5s/33nzoVpkyB1avtPVSTJvb4tm1r67xEJGKiZ0ouRGI/MO1v504bt58wAd5911aTFiliP5Hat4d27Wyvs0iY7dxp+f2tt+Dtt+H3360/UZs2cP75NoVUurTrKuOP79uuwdzwNHu2tT/IyICLL4aLLrI1YIk2tSkSYQpMMWflSgtPEybYGL7nWXi6/HLo0EELxyWkdu3aF5LGjbOQdOKJ0LmzPd00Uxx5W7fCjBkwfry9DGzcaJ1LLrsMrrzSgpSIhJwCU0z7/Xd7q//667b4oUgRG3G6/HIbt09JcV2hxCDft51sI0daSFq/3hZnd+4MnTrZ5k6NZkSHHTtg1iwYO9ZC7caNtlbsyiuhS5f8d0cRkaAUmOLGTz/B6NEWnpYuhVKl4JJL7JWzcWP9hJOg1qyxkPTyy9YwsmJFuPRSC0mZmXoKRbucHJuye+01eO89C1PNm9tLQMeO6vkkUkAKTHFp2TIYNcqu1attdWjPntCtmy0eF9lj+3Z45x0YMcJ2txUpYjm7Wzc491ydnRarNm2y0cGRI21KtVgxm7Lr2dOmURV+RQ6bAlNc830brx8xwl49wVaI9uxpe5T1qpmw1q6F4cPtqfHrr9CoEVx9tYWleP9vkWh++glefRWef97eP9WqBb16wRVX2PExIpIvCkwJY8MGe9UcPty23FStCr17wzXX6CdkgvB9a/OVlWUbLosWha5d4YYb7MgOiW+7dtli8eHDbbF4SopN1918s513JyKHpMCUcHzfFog/95ytEi1aFK691l41K1d2XZ2EQSBgWXnIEOtKkZFhWblrV2XlRLVuHbzwAgwdaic4NW8Ot9xi7SE0DSuSJwWmhPbzzzbcMGyYLXpo3x5uvdXmZzRdF/N++gn++1+bdvvrL1v427u3NT/UP6+ArWEbNw6eesoakZ58Mtx0k72HKl7cdXUiUUWBSbDGLiNH2k/XFSusRXO/fraPXE12Ys4XX8D//R+MGWM/9Hr3hj59oHx515VJNPv0UwtOb71lI4833WRXmTKuKxOJCkEDkwZnE0GxYrYK9KuvbF9y6dLWy+nUU+HFF+1tqES92bOt2/bpp8NHH8Hjj1urgIcfVliS4M480zbWrlpl07WPPWb9t/r1s8FoETm0uAlMWVlZZGRkkJmZ6bqU6FWokJ1zMX26nf552mk2Nl+1qi2A+esv1xXKfnIXcjdtatdvv9kPve++szUpmlaRw1Wxog02r15tM/QvvGDLG3v0sP5cIpI3TcklumXL4JFHbH7nmGPs7eb11+snsWO+b4ezPvCAreE/4wy47z648EKtT5LQys62PSKDB9vhAp062XPt1FNdVyYSUZqSkyBq1LAhixUrbAtN//72dvPJJzXi5IDv29bwxo3tCMFt22DiRFi0yE7FUViSUEtLgzvugB9/tD0i8+bZy8JVV8H337uuTiR6KDCJqVrVOt99952duvqvf+373M6drqtLCHPm2AbGVq3s2ItJk2DBArjgAgUlCb8iRWxweeVKePppeP99qFbNpup++sl1dSLuKTDJP1WqZPvUv/oKzj7bXi0zMuwcu927XVcXl5Yts6m2Jk3svLDJk+1w3LZtFZQk8lJTbdfl99/bwvB33rH3TjfdZAc1iyQqBSbJW7VqFpIWL7az6rp0sWPSJ02yeSMpsDVrrBF77dqwfLk93AsWwHnnKSiJe0WLwm23wQ8/wP33W2eSKlVsyeO2ba6rE4k8BSY5tNNPt6PRP/oISpa0+aGWLWHpUteVxayNG23NSNWq9tA+9RR8/TVceqm6MEv0KV7cljZ+/70F/Pvus/dQI0dq0FkSi16eJX/OPtsO+n33XVvQUKeO9XbSGH2+7dhha+lPOsm6ONx1l/0QuvFGO/dLJJqVKWPtCJYvt55OV10F9epZ2wuRRKDAJPnnebZVa9kyeOIJePNNG6N/7DFbfCMHNX26nSJ/++1w2WW2tv7++6FECdeViRyeqlVh7Fhrd5GcDM2a2Rq8r792XZlIeCkwyeFLSYG+fe2nfvfuMGCANW0ZO1brm/bz/fd2hF/r1nDssfD553Yg6nHHua5MpGAaNbLNCaNH23uomjXtjO9Nm1xXJhIeCkxy5MqUsf3Hy5bZTrpOnawd9Zdfuq7MuT//tByZkWHr5seMsamL2rVdVyYSOp5na+9WrLDF4C++aPtFXn5Z65sk/igwScFVr26rl6dNszVNdepYH6c//3RdWcT5Prz+uv3QePJJWyy7YoWdc6ydbxKvUlNtI8M330Dz5nD11TYC9fnnrisTCR0FJgmdVq3giy/gwQetZXD16gk1TbdsGZxzDlx5JTRsaEHp/vvt7GORRHD88XZwwMyZduRKvXrQuzf873+uKxMpOAUmCa2UFBtWWb4c6ta1abrzzrP1TnFqyxbb8Vanjp3F9cEH8NZb1gNUJBE1bWpT0YMH24hr9eoWpBLkvZPEKQUmCY8TT7QWBO++a0MtNWrYcEucnU/33ntw2mm23fq++2yArVkz11WJuJecbHtDVqyAc8+FK66w904//OC6MpEjo8Ak4dWunY029etnq0Lr1LEmmDHu99+t+fmFF9p6pWXL4O67bS2HiOxTrpxtepg40V4KTjsNHn9cR1RK7FFgkvArVgweftjG6NPToXFjO6wqO9t1ZYfN9+GNN2z32/Tp1u146lRrRyUiB3fBBRaYevWCO++E+vXhs89cVyWSf3ETmLKyssjIyCAzM9N1KXIwp50GH39s81cvv2y/nzTJdVX59vPPNmB2+eU2xbB8uS3w1u43kfwpXtx2j86fb20H6te38+q2bHFdmUhwnh9bq/CCFpudnU16ejqBQIC0tLRI1CRH4scf7a3m9Ok2t/XMM9bXKQr5Przwgs0qFitmx5p07Oi6KpHYtmOHvXe6917bXffSSzb4LOJI0Le+cTPCJDHmxBNtLuvVV+1jjRpROdr0ww921nCPHnDRRTaqpLAkUnDJydau7YsvrAt+kya2SHzrVteVieRNgUnc8Tzo2tVWTNepY4scrrsuKtY27d5tg141asC331qme+klKFXKdWUi8eWUU2DOHDuectgwO3Nx7lzXVYkcSIFJ3Ctf3kaXhg+37TS1asGsWc7KWb0aWrSwc7G6d7c817q1s3JE4l5SEtx66z9Hm267Le66kEiMU2CS6OB5Nu+1dKl1fDz3XHsF3bYtYiX4vq1Fr1nTRpXef98alpcoEbESRBJa7mjT44/b/7369XU0pUQPBSaJLpUr27kKgwfD0KFwxhmwcGHYv+0ff8DFF9sZWB072ot08+Zh/7Yisp+kJBtdWrTI3sTUq2c763SYr7imwCTRp1AhG11avNj2ITdoAPfcY9tqwuDDD20WcPZsGDcOXnkFSpYMy7cSkXyqWdPeK/XpYwGqdWtr7SHiigKTRK9TT4VPPrEzRwYNsj3Hq1aF7Mtv324N9Fq0sG7dS5faTjgRiQ5Fithg8/TptkO1Vi17UyPiggKTRLfkZBtd+vhjO4/k9NPtNM8CWrkSGja0F+NBg2DGDOsFIyLRp2VLe0Nz7rlwySU2db55s+uqJNEoMElsOPNMm6Jr397aa1911RG9Yvo+vPiidTHIzoZ582yUKSkpDDWLSMiUKQNvvWXtPcaOtfdOn3ziuipJJApMEjvS0uzwtldfhfHjLfUcxoLwjRuhc2e49lq47DL4/HNbUCoiscHzrNXHkiXWfqBxYzumUgvCJRIUmCT2dO1qr5hlyti82n/+E/QV86OPbP3D++/bu9QXXrD15CISe04+2doPDBhgM/bnnQfr17uuSuKdApPEppNPthR0++1w113WJXzDhgNutnu35ammTa1jwdKltgZCRGJb4cLw4IMwbZrN1p9+uu10FQkXBSaJXcnJtmJ7yhRYsMCm6P62qOGPP6BdO8tTd9xh7QMqVnRYr4iEXMuW1iG8WjVo1gweegh27XJdlcQjBSaJfW3a2BRdpUp2psITTzDvE586dWD+fJg8GR55xN6Rikj8KVfOptvvuQfuvddeEn77zXVVEm8UmCQ+VKgAM2fi970Vbr+d9Y06klFuI4sX2/oGEYlvSUlw//3WIuTLL22KbuZM11VJPFFgkrixaUsyHb99jAuZQMvUOUxZfwYVfw3/sSoiEj2aN7cB54wMa0r76KPWTkSkoOImMGVlZZGRkUFmZqbrUsSBL7+EzExb9NlzwoUU+/pzvGOOgUaN4PnnXZcnIhF03HHWHXzAAOjf3zZ6ZGe7rkpinefHVvQOWmx2djbp6ekEAgHS0tIiUZM4Nnq09VaqUgXefts20AGQkwN9+8Jzz0HPnvD005Ca6rJUEYmwd9+1Prfly1v7turVXVckUcoLdoO4GWGSxLNjhx3K2aULdOxoXbv3hiWwcDR0qDVdevllWxC+dq2rckXEgfbtrb9toUI2Cv32264rklilwCQx6bffbDvxM8/YwNHIkVCs2EFufM011rPp55+hbl3reCciCeOUU+DTT20DyMUX2zSdWg/I4VJgkpgzf77lnhUrrLfSTTfZkQmHlJkJn31mK0GbN7eUFVvT0SJSAMWLw5gx8Pjj8Nhj1nogj163IgelwCQxw/dh2DA45xw44QQ7C65x48P4AsccY3uOb74ZbrnFjljZujVs9YpIdPE86NfPXgaWLLE3Xp995roqiRUKTBITtm+H66+3q0cPmDXLFnEetsKF4YknYNQoW8zQsCGsWhXqckUkijVrZm+4jj0Wzj7bzvMWCUaBSaLehg3QqhW89JJ1CMjKgpSUAn7RLl1sbm/zZpuumzUrFKWKSIyoWNGWM15xBXTrBv/6l9Y1yaEpMElUW7YM6teH5cttvdK114bwi9eqZdtn6tSxFeTDh4fwi4tItCtSxN6E/fe/MHiwnT2pfk1yMApMErUmTIAGDaBECcs1jRqF4ZuULm2H9/bsCb162fqmnTvD8I1EJBp5ni1pnDwZPv4YzjoLvvvOdVUSjRSYJOr4vh1n0KGDHW3w8cd2rm7YJCfbPF9WFgwZAuefD5s2hfEbiki0ad3aWg/s3Alnnmkj2iJ/p8AkUeWvv2zzWv/+MHAgjBtn24EjondvmDbNhrPOOgu+/TZC31hEokG1ahaazjjD1k0OGeK6IokmCkwSNdats2bc48bBG2/Agw9ad96Iat7cXjHB3mZ+8EGECxARl0qVsln6Pn3s6t3bThUQUWCSqLB4sW1W+/lnmDsXLrvMYTFVq9oOunr1bJx+6FCHxYhIpBUuDE89ZftARoywJpcbN7quSlxTYBLnJk2yBpTlytlsWL16risCSpa0VaC9e9t1441aDC6SYHr0gPfftyaXatkmCkziVFaWbeVt0cJaIZUr57qivylc2I5Qee45azHerp31bRKRhNGkiQ045y4G/+QT1xWJKwpM4sSuXXDbbTZwc/PNtm7pqKNcV3UQvXrZMNhHH9m5LL/84roiEYmg3Fn6U0+1LuFjxriuSFxQYJKI27oVOnWyNQLPPANPPglJSa6rCqJVK+tvsGGDvc388kvXFYlIBJUpY2fQdepkaywfeUTndyeauAlMWVlZZGRkkJmZ6boUOYTffoOmTW33/rvv2ghTzKhZ095mli1rB1DNmOG6IhGJoNRUO3fu/vut7ck119g5l5IYPD+2InLQYrOzs0lPTycQCJCWlhaJmiSfli+Htm3tBea996zXSUzavBk6d7bVoMOHw9VXu65IRCLs9dftv37TpjB2LOjHTczzgt0gbkaYJLp9+KHtMklL29cYLmaVKAETJ9rby2uugXvv1di8SIK54gobKV+wQEsbE4UCk4TdK69YO6Mzz7R10xUruq4oBAoXtt1zjz5qHTavukpj8yIJ5txz7TXtjz/s3Mvly11XJOGkwCRh4/swaBB0727Xe+/F2bC158Gdd8Lo0fDmm5YK1d1OJKHUqGFLG0uWtKWNc+a4rkjCRYFJwmLXLmsXMGCALZAcPtzOuI1Ll15qR6gsXWodONeudV2RiETQ8cdbUKpbF1q2tPdPEn8UmCTkcnKgSxc7uPK55+C++2wwJq41amRtBzZvtsVaGpsXSSjp6XY4QOfO9h5q8GAtbYw3CkwSUoGAnbs0YYI1o+zVy3VFEVS9OsybZ2PzjRqpJbBIgklJsbYD/ftDv37WnHf3btdVSagoMEnI/PKL7RZZssR23Hfo4LoiB8qXt7H5mjWheXNLjiKSMDzPmlpmZVlzXu0HiR8KTBIS33xjM1H/+5/tGmnUyHVFDpUsafuN27aFjh3h+eddVyQiEda79779IO3awZYtriuSglJgkgL79FPbHVKsmM1CnXaa64qiQJEi9krZq5cdef7QQ1rQIJJgOneGKVNseWPz5tZ+QGKXApMUyOTJdhhl9epx1GMpVJKSbFz+wQfhnnvsHJhdu1xXJSIR1Lw5zJoFq1bZJto1a1xXJEdKgUmO2Msv21BzixZ2rFrp0q4rikKeB3ffDSNG2JbByy/XggaRBFO3ro0ybdumTbSxTIFJjsjgwXaO0jXX2G64okVdVxTlrrvODpx65x1o3x62bnVdkYhEUNWqFppKlbKRpvnzXVckhyvsgcnzvN6e5/3ged5fnud95nle40PctqnneX4eV/Vw1yn54/t2dFq/ftaUctgwOyVE8qFjR5vDnDsXWrWCTZtcVyQiEZS7iTYjw6bqpkxxXZEcjrAGJs/zLgX+CzwM1AHmAlM8zzshyF2rAeX+dn0bxjIln3bvhltusSU5//kPPPxwAjSkDLXmza0r+PLldsz5b7+5rkhEIqhkSZg+3ZYytGtnO+kkNnh+GHfueJ73KfC57/s3/O1zXwPv+L7fP4/bNwVmAqV839+Ux5c8oNicnBxycnL2/j47O5uKFSsSCARIi6uDy9zauROuvRZGjoShQxOsIWU4LFtmo0xHHWVNqypVcl2RiETQ319Thw2zzbTiVNC3/2EbYfI8LwWoC0zf74+mAw2D3H2x53nrPM/7wPO8cw91w0GDBpGenr73qqhtWiGXkwOdOsGoUfD66wpLIVGjhm0r3L3bejJ8/bXrikQkggoXhpdesn5NPXvaulCJbuGckisLJAH7zzn8Bhx3kPusA3oCFwMXAd8AH3ied87Bvkn//v0JBAJ7rzXasxlSf/4JF1wAU6fC+PF2RpyEyEknWWjKXQW6aJHrikQkggoVgmeesfWg/frZuZtq1xa9IrFcd/9/fi+Pz9kNff8bLCTlmud5XkXgdmBOXvdJTU0lNTU1FHXKfjZutGbVy5bZ4sSmTV1XFIfKlYPZs+H88+Hcc2HiRD3QIgnE82w9aFoa3HUXZGfbaJPWh0afcI4wbQB2ceBo0jEcOOp0KPOBqqEqSvLn11/t5/bKlfDhh/oZHlalS1sjq7POspOLJ050XZGIRNidd8KQIXb+3HXXqcdtNApbYPJ9fzvwGdByvz9qCRzOMe51sKk6iZDVq22G6PffbQtsZqbrihJA8eLw3ns20tSxo7bOiCSgG26AV1+FV16x5Q/qcRtdwj0lNxgY6XneImAetj7pBOA5AM/zBgHH+75/1Z7f9wV+BL4CUoArsfVMF4e5TtljxQpo2RJSUmx5zUknua4ogaSmwpgxtnXm8sutLfDVV7uuSkQi6MoroUQJO4euQwfrd1usmOuqBMIcmHzfH+N5XhngXqyf0jKgre/7q/fcpBwWoHKlAI8DxwPbsOB0vu/7k8NZp5glSywsHXus9QkpX951RQkod+tM0aLWRn3bNttGIyIJo317mDTJPp53ns3Sq0uOe2HtwxQGQYvNzs4mPT1dfZgO08KF0Lq1jShNmwZlyriuKMH5Ptx6qy1oePxx20IjIgnlk09s403Vqva6rPM6w8pdHyaJHZ98Yl1nq1WzHooKS1HA8+DJJ6F/f7j9dmuvHltvbkSkgBo2hFmz4Mcf7ZCADRtcV5TYFJgS3OzZ1nC6dm2bhitZ0nVFspfnwSOPwEMP2QF+AwcqNIkkmNNPh5kz4ZdfrPOITlNyR4Epgb3/vs2Pn3WW9VkqUcJ1RZKngQPhiSdg0CCbplNoEkkoNWrYm9s//rAWL+u0b9wJBaYENXmydfBu2tQWFB51lOuK5JBuu21fk5brr7cjVUQkYVSvbqHpzz+hSRNYu9Z1RYlHgSkBvfOObVdt08aOOyla1HVFki833GA76J5/Hrp3t9M7RSRhVK1qvfG2b7fQtHp18PtI6CgwJZgxY+CSSywwvfWWtf6RGNK9u52C/MYb1rBFoUkkoVSubCNNAOecA6tWua0nkSgwJZCRI60f4uWX28/c5GTXFckRufRSS77jxtk/5o4drisSkQiqVMlCU2qqhaZvv3VdUWJQYEoQzz8P3bpZL8SXXrL+iBLDLrrIhgjHj1doEklAFSpYaEpLs+m5r792XVH8U2BKAMOGQY8e1jB62DBISnJdkYRE7rkJ774Ll12mg6dEEky5ctanqWxZ28CzbJnriuKbAlOcGzrUNlXdcgs88wwU0r94fGnf3qbmJk60qTqFJpGEcswx8OGHdpRV06Z2xJWER9z8+MzKyiIjI4PMzEzXpUSNoUNtVOmWW6xptBe08bvEpAsvhLfftl4RnTopNIkkmLJl4YMPbEF4s2awaJHriuKTzpKLU0OGQJ8+0LcvDB6ssJQQJk+2tU2tWmkLpEgCCgSsXczy5XZyw5lnuq4opugsuUSksJSg2ra1JlvTp8PFF8Nff7muSEQiKD3d/vvXrGnvmxYscF1RfFFgijNZWRaWbr1VYSkhtWkDEybY+PxFFyk0iSSYEiXsqKsaNSw0LVzouqL4ocAUR7Ky4MYbLSw98YTCUsJq1cpC08yZtpNOoUkkoeSGpowMaNlSa5pCRYEpTuSGpdtuU1gS7FXyvffsHIX27WHbNtcViUgEpaXB1Klw6qn2cvDZZ64rin0KTHHg72Hp8ccVlmSP5s0tNM2dC+3awdatrisSkQjKDU3Vqllo+vxz1xXFNgWmGPfssxaW+vVTWJI8NGtmu+c++UTTcyIJKD0dpk2zg3tbtIDFi11XFLsUmGLYs8/CTTdZWPq//1NYkoNo2tRGmj76CDp2hJwc1xWJSATlhqYqVSw0qbnlkVFgilFDhigsyWE499x9C8HV3FIk4ZQsaS0HTjrJZuu/+MJ1RbFHgSkGjRixr3WAwpLkW4sW1qdp2jQ7e04H9ooklNzQVLmyQtORUGCKMa+8Ar16WWDSbjg5bG3a2Nlz770HV1wBO3e6rkhEIqhUKZgxAypVstC0dKnrimKHAlMMeeMNuOYauO46ePpphSU5QhdcAGPG2Plz3brBrl2uKxKRCMoNTSecYKHpq69cVxQbFJhixNix0LWrXc89B4X0LycF0bGjJfAxY+Daa2H3btcViUgElS4N778P5ctbaFq50nVF0U8/dmPAu+9Cly5w6aXwwgsKSxIinTrByJF29eql0CSSYHJDU5ky1oFk1SrXFUU3/eiNclOm2M+1Dh1s/VJSkuuKJK506QIvvWRJ/MYbwfddVyQiEXT00RaaihWz0LR6teuKopcCUxR7/32bOWnbFkaNgsKFXVckcemqq+D552HoULjlFoUmkQRTrhx8+KHNXjRvDj//7Lqi6KTAFKVmz7bTLJo3t2UmycmuK5K4ds01tjjumWfg9tsVmkQSTIUKFpq2b7efO7/95rqi6BM3gSkrK4uMjAwyMzNdl1JgH38M558PZ59tO8BTU11XJAmhVy9rHz94MAwYoNAkkmBOPNFCU3a2tW3bsMF1RdHF82PrRTFosdnZ2aSnpxMIBEhLS4tETSG1YIE9UevWhUmTbF5ZJKKefNJOcr73XnjgAdfViEiErVgBTZrYDroPP7Q2BAkgaKMerYqJIp9/Dq1aQa1aMHGiwpI4cuut1gX8zjttLvjuu11XJCIRVL26raFt2hRat7Zfx+D4Q8gpMEWJpUuhZUuoVs0Oly9e3HVFktDuuMNC0913W3K/7TbXFYlIBNWsac0tmze3jUdTp+rnkgJTFFi+3KbhTjzRnpRK8hIVBg6ErVvthOdixeD6611XJCIRdMYZ9jOpZUu48EItE4mbRd+xauVKS/DlytmhiAkyVyyx4qGHrNXADTdYIzARSShnnmmzHgsWWJubv/5yXZE7CkwO/fijhaXSpW3os0wZ1xWJ7MfzbBF4jx7WeuDNN11XJCIR1qiRraudM8caKW/f7roiNxSYHPnlFwtLqam2oO6YY1xXJHIQnmdNLbt0gSuusFdOEUkozZrBO+/YTEiXLrBzp+uKIk+ByYENG2xOePt2+OADm44TiWpJSfDyy9ZN9ZJLLOWLSEJp3doOgp8wwQacE+34SQWmCAsE7Em3YYOFpUqVXFckkk+FC8Mbb9jQaPv28NFHrisSkQi78EI7r/u11xLv+EkFpgjassW2Z/7wg61ZOuUU1xWJHKaUFGs/f+aZ9mReuNB1RSISYZddBiNG2Ez9XXclTmhSW4EI+esve1O+dKmNLNWq5boikSNUtKiNybdqZcOls2bpCS2SYK69Fv78E/r2hRIlEqO/rQJTBOzYAZ072xlxU6dC/fquKxIpoOLFba9x8+a2IG/2bGsPLCIJ45ZbYPNmuOcee0no29d1ReGlKbkw27ULrrrKgtL48XY+j0hcKFkSpk2Do4+2zqs//OC6IhGJsIED7WCAW2+FF15wXU14KTCF0e7ddgD8m2/aWtk2bVxXJBJiZcvagryiRW3f8dq1risSkQjyPHj0Uett26MHjB7tuqLwUWAKE9+347deeMF2Y198seuKRMKkXDlbmLd7t03RrV/vuiIRiSDPg2efhSuvhK5d47dVmwJTmNx7Lzz1FAwZYk8gkbh2wgkWmrKzbSH4pk2uKxKRCCpUCF580Vq1depkLwfxJm4CU1ZWFhkZGWRmZrouhccesyO4HnvMhilFEkKVKtYGePVqOP9866MhIgmjcGEYNQrOPdeC0yefuK4otDw/thooBC02Ozub9PR0AoEAaWlpkajpH4YMgT59bNfAv/8d8W8v4t6CBTY117ChtR9ITXVdkYhE0NatcN558MUXMHMm1KnjuqJ88YLdIG5GmKLBK69YWOrbFx54wHU1Io7Ur29BafZsuPzyxDx0SiSBFStm65hOOcXatX39teuKQkOBKUTGjrWzda67DgYPtkVwIgnr3HPhrbfg3Xdt60yiHTolkuDS0mDKFDjuOOs6smqV64oKToEpBCZPtjfSl10Gzz2nsCQC2KFTr75qQ6+33po45yeICABlyljXkaOOstD088+uKyoYBaYCmjXLWga0bWvtA5KSXFckEkUuv9wW9j39NNx/v+tqRCTCjjsO3n/fmji3aBHbXUcUmApg4UJ7E92okTXrSk52XZFIFLr+euts9+9/23y1iCSUE06w0LRxY2x3HVFgOkLLl9sugBo17MiTIkVcVyQSxe68E/r3h3794PnnXVcjIhFWtapNz61eDRdcYDvpYo0C0xH48Udb+V++vK1fKl7cdUUiMeDhh6F3b+jZ084LEpGEUrOmLQRfssSWsmzf7rqiw6PAdJh+/dUOZy9SxM4dLVXKdUUiMcLz4Jln4Ior7AyFKVNcVyQiEXbmmbZ59sMP7RSMXbtcV5R/CkyHIXf+dcsWG1osV851RSIxJvf8hLZt4aKLYM4c1xWJSIQ1b27rfseOtdMwYmUDrQJTPm3ZYvOua9daWKpc2XVFIjEqOdleLRs2tP9Un33muiIRibCOHe1w+hEj4K67XFeTP4VdFxALtm+3+dYvvrBhxNNOc12RSIwrUsTG5Vu0sGHbOXMgI8N1VSISQd272465W2+15S3RHpw0whTErl223GLmTHt9r1/fdUUicaJ4cds1Ub68LQz84QfXFYlIhPXtC/fea5tohw1zXc2hKTAdgu9bC5lx42DMGJt3FZEQKl0apk+3w6datIB161xXJCIRdv/9cNNNtp5p9GjX1RycAtMh3HWXtYx58UXo0MF1NSJxKrcV8PbtNtL0xx+uKxKRCPI8+O9/bddc16428ByNFJgO4tFH4bHH7B+xWzfX1YjEuUqVbDfF+vXWEXbzZtcViUgEFSpki8DbtrU1w3Pnuq7oQApMeRg2zOZT77sPbrnFdTUiCaJ6dWtu9s030K4dbNvmuiIRiaDChW35S4MGtoF28WLXFf1T3ASmrKwsMjIyyMzMLNDXGT3a5lFvuskCk4hEUJ06MGkSfPopXHop7NjhuiIRiaDcDbTVqtkG2m++cV3RPp4fKx2jTNBis7OzSU9PJxAIkJaWdlhffPJkaN8eunSBl1+2IUIRcWDqVBtluvRSeOUV/WcUSTB//AHnnGOz8x99ZAf4hpkX7AZ6Fdpj7lybN23b1uZR9fos4lCbNvDaa/D663DzzbHTClhEQqJMGdtAm5Rke0HWr3ddkQITYPOkF1xg86ZjxlgjYhFxrHNnW1CYlWWNWkQkoRx/vO0FCQTsPVQg4LaehA9MK1faPOkpp9i8aZEirisSkb169LDtqg89BIMHu65GRCKsShUbafrhB7jwQti61V0tCR2Y1qyxXnlly9rB6SVKuK5IRA7wr3/ZttV+/awpmogklFq1bI3xZ59Bp07Wss2FhA1Mv/9u86KFCll6LVvWdUUiclAPP2zbV3v0sCPORSShNGgA77xjPW67dbNjyyItIQ/fzZ0P3bTJVt9XqOC6IhE5JM+DZ5+1/7SXXw5padCqleuqRCSCWraEN96wUaaSJWHIEHtpiJSEG2Hats12K69aZT3yqlRxXZGI5EuhQtZioFUr6NgRPvnEdUUiEmEXXQQjRsBzz8HAgZH93gk1wrRjhyXThQttWK92bdcVichhSU6Gt96yIeLzz4fZs22Bg4gkjGuuscHmfv2gVClb5hgJCROYdu+G7t1tvdLEidCwoeuKROSIFC1q/4nPPddGm+bOhapVXVclIhF0222wcSPccYdNz/XoEf7vmRBTcr5vR5288Yb1wWvd2nVFIlIgaWnWDbxUKVvYsHat64pEJML+/W/o0wd69YI33wz/90uIwHTvvbY4bNgwm5ITkThw9NE2ZOz7NtK0YYPrikQkgjwPnn7a9oFceaWtSw6nuA9Mgwdbz7vHHovMkJ2IRFDFirYg8Y8/bF1TdrbrikQkggoVgpdespmjiy6CefPC+L3C96Xde/FFWxTWv3/kFoWJSIRVrWojTd99Z1tgt21zXZGIRFBysk3J1atn58F++WV4vk/cBqZ337URpeuvt553IhLHateGSZNgwQI7g27HDtcViUgEFS0KEyZA5co2Q79qVei/h+fH1ingQYvNzs4mPT2d5OQAF1+cxmuv2WnHIpIApk2zA6c6dYKRI228XkQSxvr10KgR7NxpjanLl8/3XYO2wIyZwOR5nhcIBHbv//mcnBxycnL2/n7evC107lydpk3X8NZbaaSkRLRMEXFt/Hi4+mq49lp4/PHItgIWEed++slGmUqWhBkz8ndObHp6ejqw2T9EKIqlwJQGBFzXISIiInEp3ff9g+4ciaXAlK8RpnXr1lG/fn2WL1/O8ccff8TfLzMzk4ULFzq7v+sasrOzqVixImvWrCEtLc1JDaG4v+sa4uVxdP3vcESP49NPwz332DbZm24qcA3RcP+Cfg09H0PzNfQ4huZrhOJxDNXfYeXKlUFHmGKm0/eh/hJ5KVGiRIGeyElJSU7vHy01pKWl6XHU4xgV/w5wmI/j3Xfbjrm774bjjoNrr3X+OMTk4xiGGlzfP1RfQ4+j+8cxVH+HQ40s5YqZwBRpffr0cXr/aKmhoKLh7xANNRSU679DNPw7HJGHHrJDp3r2hPR0549DzD6OIa7B9f1D9TVc1+D6/qH6Gq6/f36/RsxMye0RtNi1a9fuHeKrUKFCJGqKS7m7DQOBQIHTeyLT4xgaBXocd++Grl3t0N6JExP6bCQ9H0NDj2NoRNnjGHR3SNztuU1NTf3HRzkyqamp3HfffXocC0iPY2gU6HEsVAhefnlfK+BPPgl5fbFCz8fQ0OMYGrH2OMbdCFOUJVYRiRbbtsF558GSJTB7tjW7FBExiTfCJCKSp9xWwFWqWJOWb791XZGIxBAFJhFJHGlpMHUqlC4NLVrA2rWuKxKRGKHAJCKJpWxZa//redCyJfz+u+uKRCQGKDCJSOKpUMFC08aNtq4pO2gLFhFJcApMCWzIkCFUrlyZIkWKULduXebOnXvQ286aNQvP8w64VqxYEcGKo8+cOXO48MILKV++PJ7n8c477wS9z+zZs6lbty5FihThpJNO4rnnngt/oVHucB/HkDwfq1a1w3q//x7atbNF4TFs0KBBZGZmUqJECY455hg6dOjAN998E/R+ej7+05E8jnp9PNDQoUOpVavW3qaUDRo0YMqUKYe8T7Q/FxWYEtSYMWPo27cvAwcOZPHixTRu3JjzzjuPn3766ZD3++abb1i3bt3eq2rVqhGqODpt2bKF2rVr8+yzz+br9j/88ANt27alcePGLF68mAEDBnDzzTczbty4MFca3Q73ccxV4Odj7dowaRIsXAidO8OOHYd3/ygye/Zs+vTpw/z585kxYwY7d+6kVatWbNmy5aD30fPxQEfyOObS6+M+FSpU4NFHH2XRokUsWrSIZs2a0b59e7766qs8bx8Tz0Xf92PpCioQCPiAHwgE8nPzhFW/fn3/+uuv/8fnqlev7t9111153n7mzJk+4G/cuDEC1cUmwB8/fvwhb3PHHXf41atX/8fnevXq5Z911llhrCy25OdxDPnzcepU309O9v3LL/f9XbtC8zUdW79+vQ/4s2fPPuht9HwMLj+Po14f86dUqVL+888/n+efRcFzMWgG0QhTAtq+fTufffYZrVq1+sfnW7VqxSdBmvrVqVOHcuXK0bx5c2bOnBnOMuPSvHnzDnjcW7duzaJFi9gRw6MbroTs+di6NYwaBaNH20G9sdWfLk+BQACA0qVLH/Q2ej4Gl5/HMZdeH/O2a9cuRo8ezZYtW2jQoEGet4mF56ICUwLasGEDu3bt4thjj/3H54899lh+/fXXPO9Trlw5hg8fzrhx43j77bepVq0azZs3Z86cOZEoOW78+uuveT7uO3fuZMOGDY6qij1heT5ecgkMHw5DhsA994SuWAd83+e2226jUaNG1KhR46C30/Px0PL7OOr1MW9ffvklxYsXJzU1leuvv57x48eTkZGR521j4bmow3cTmOf9s7Gp7/sHfC5XtWrVqFat2t7fN2jQgDVr1vD4449zzjnnhLXOeJPX457X5+XgwvZ8vPZaO6z39tuhVCno16/gxTpw4403snTpUj766KOgt9Xz8eDy+zjq9TFv1apVY8mSJWzatIlx48bRrVs3Zs+efdDQFO3PxbgZYcrKyiIjI4PMzEzXpUS9smXLkpSUdMBo0vr16w9I+Idy1lln8a26JR+W4447Ls/HvXDhwpQpU8ZRVfEhZM/Hfv1g4EALTS+8UPCvF2E33XQTEyZMYObMmUEPINfz8eAO53HMi14fISUlhSpVqlCvXj0GDRpE7dq1eeqpp/K8bSw8F+MmMPXp04fly5ezcOFC16VEvZSUFOrWrcuMGTP+8fkZM2bQsGHDfH+dxYsXU65cuVCXF9caNGhwwOM+ffp06tWrR3JysqOq4kNIn48PPgh9+kDPnjB2bGi+Zpj5vs+NN97I22+/zYcffkjlypWD3kfPxwMdyeOYF70+Hsj3fXJycvL8s5h4LuZnZXgUXUFpl1z+jB492k9OTvZfeOEFf/ny5X7fvn39o446yv/xxx993/f9u+66y+/ateve2z/55JP++PHj/ZUrV/rLli3z77rrLh/wx40b5+qvEBU2b97sL1682F+8eLEP+IMHD/YXL17sr1692vf9Ax/HVatW+cWKFfNvvfVWf/ny5f4LL7zgJycn+2PHjnX1V4gKh/s4RuT5uGuX7ZpLTrZddFHuhhtu8NPT0/1Zs2b569at23tt3bp17230fAzuSB5HvT4eqH///v6cOXP8H374wV+6dKk/YMAAv1ChQv706dN934/K52LQDOI6ACkwOZSVleVXqlTJT0lJ8c8444x/bJvt1q2b36RJk72//89//uOffPLJfpEiRfxSpUr5jRo18idNmuSg6uiSu514/6tbt26+7x/4OPq+78+aNcuvU6eOn5KS4p944on+0KFDI194lDncxzFiz8ft233/ggt8v1gx3//449B//RDK6/ED/JdeemnvbfR8DO5IHke9Ph7ommuu2fvz5eijj/abN2++Nyz5flQ+F4NmEM+Pre2zQYvNzs4mPT2dQCBAWlpaJGoSkXi2bZsdn7JkCcyebc0uRSTeBF1ZHjdrmEREwqJoUZgwAapUgVatIMEX8ookKgUmEZFg0tJg6lQoXRpatIC1a11XJCIRpsAkIpIfZcvCjBngedCyJfz+u+uKRCSCFJhERPKrQgULTRs32rqm7GzXFYlIhCgwiYgcjqpVYdo0+P57uPBCWxQuInFPgUlE5HDVrg2TJsGiRdCpE0TJ4aAiEj4KTCIiR6JhQ3j7bZg+Hbp3h927XVckImGkwCQicqRat4ZRo2D0aLjxRoitvnYichgUmERECuKSS2D4cBg6FO6+23U1IhImhV0XICIS8669FjZtgttvh1Kl7KOIxBUFJhGRUOjXz9oN/OtfULIkXHed64pEJIQUmEREQuXBB22kqWdPSE+3HXQiEhcUmEREQsXz4OmnLTRdcQWUKAFt2riuSkRCIG4WfWdlZZGRkUFmZqbrUkQkkRUqBC+9ZEHpoovg449dVyQiIeD5sbUNNmix2dnZpKenEwgESEtLi0RNIiIH2rbNjk9ZsgRmzYLTT3dckIgcghfsBnEzwiQiElWKFoUJE+woldatYeVK1xWJSAEoMImIhEtaGkyZAmXKQMuWsGaN64pE5AgpMImIhFPZsnZ8iudZaPrtN9cVicgRUGASEQm3ChXg/fchO9tC0x9/uK5IRA6TApOISCRUqQIffAC//mprmjZtcl2RiBwGBSYRkUg59VSYMQNWrYK2bWHzZtcViUg+KTCJiERS7dowbRp89RW0awdbt7quSETyQYFJRCTSMjNh8mRYuBA6doScHNcViUgQCkwiIi6cfbb1aZozBzp3hh07XFckIoegwCQi4kqz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\n", "text/plain": [ "Graphics object consisting of 2 graphics primitives" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Plots can be \"added\" to overlap -- run \"plot?\" or \"help(plot)\" for plotting options\n", "p1 = plot(sin(x),x,0,pi)\n", "p2 = plot(cos(x),x,0,pi,color=\"red\")\n", "p1+p2" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "Graphics object consisting of 20 graphics primitives" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Common plot options include\n", "# plot_points (default 200)\n", "# xmin and xmax\n", "# color\n", "# detect_poles (vertical asymptotes)\n", "# alpha (line transparency)\n", "# thickness (line thickness)\n", "# linestype (dotted with ':', dashdot with '-.', solid with '-')\n", "# Use commands list p.set_aspect_ratio, etc.\n", "\n", "pp = plot([]) # Define empty plot\n", "cols = rainbow(20) # Define 20 evenly spaced colors\n", "for k in range(20):\n", " pp = pp + plot(log(x+k),1,10,color=cols[k],thickness=2)\n", "\n", "pp # Print superimposed graphs" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "Graphics3d Object" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 3d plots are similar (user may need to load the 3D viewer after running this code)\n", "var('x y')\n", "f(x,y) = x^2 + sin(x)*cos(y)\n", "plot3d(f, (x,-1,1), (y,-1,1))" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}1 x + \\frac{1}{2} x^{2} + \\frac{1}{3} x^{3} + \\frac{1}{4} x^{4} + \\frac{1}{5} x^{5} + \\frac{1}{6} x^{6} + \\frac{1}{7} x^{7} + \\frac{1}{8} x^{8} + \\frac{1}{9} x^{9} + \\mathcal{O}\\left(x^{10}\\right)\n", "\\end{math}" ], "text/plain": [ "1*x + 1/2*x^2 + 1/3*x^3 + 1/4*x^4 + 1/5*x^5 + 1/6*x^6 + 1/7*x^7 + 1/8*x^8 + 1/9*x^9 + Order(x^10)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The series command computes power series of symbolic expressions representing functions\n", "show(log(1/(1-x)).series(x,10))" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}{(-1)} {(-\\frac{1}{2} \\, \\pi + x)}^{(-1)} + \\frac{1}{3} {(-\\frac{1}{2} \\, \\pi + x)} + \\frac{1}{45} {(-\\frac{1}{2} \\, \\pi + x)}^{3} + \\frac{2}{945} {(-\\frac{1}{2} \\, \\pi + x)}^{5} + \\frac{1}{4725} {(-\\frac{1}{2} \\, \\pi + x)}^{7} + \\frac{2}{93555} {(-\\frac{1}{2} \\, \\pi + x)}^{9} + \\mathcal{O}\\left(\\frac{1}{1024} \\, {\\left(\\pi - 2 \\, x\\right)}^{10}\\right)\n", "\\end{math}" ], "text/plain": [ "(-1)*(-1/2*pi + x)^(-1) + 1/3*(-1/2*pi + x) + 1/45*(-1/2*pi + x)^3 + 2/945*(-1/2*pi + x)^5 + 1/4725*(-1/2*pi + x)^7 + 2/93555*(-1/2*pi + x)^9 + Order(1/1024*(pi - 2*x)^10)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The series command can also compute Laurent series\n", "show(tan(x).series(x==pi/2,10))" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "# Series are not symbolic expressions, but symbolic series (note the Symbolic Ring is the parent of both)\n", "# This means some methods available to symbolic expressions may not be available for symbolic series\n", "ser = arctan(x).series(x,10)\n", "print(type(ser))" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1/9*x^9 - 1/7*x^7 + 1/5*x^5 - 1/3*x^3 + x\n", "\n" ] } ], "source": [ "# To go from a series expression to the polynomial defined by its terms, use the truncate command\n", "pol = arctan(x).series(x,10).truncate()\n", "print(pol)\n", "print(type(pol))" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cos(x)\n", "-cos(x)\n", "sqrt(pi)\n" ] } ], "source": [ "# The diff/differentiate command computes derivatives\n", "# The integral/integrate command is similar\n", "print(diff(sin(x),x))\n", "print(integrate(sin(x),x))\n", "print(integrate(exp(-x^2),x,-infinity,infinity))" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ ".NewSymbolicFunction'>\n", "-sin(f(x))*diff(f(x), x)^2 + cos(f(x))*diff(f(x), x, x)\n", "cos(x)*D[0](g)(sin(x), f(x)) + diff(f(x), x)*D[1](g)(sin(x), f(x))\n" ] } ], "source": [ "# This also works with abstract symbolic functions\n", "var('x y')\n", "function('f')(x)\n", "print(type(f))\n", "print(diff(sin(f(x)),x,x))\n", "function('g')(x,y)\n", "print(diff(g(sin(x),f(x)),x))" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1/2*y(x)^2 == 1/2*x^2 + _C, 'separable']" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Here we set up and solve a differential equation\n", "x = var('x'); y = function('y')(x)\n", "desolve(y*diff(y,x) == x, y, show_method=True)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1/(s^2 + 1)\n", "sin(x)\n" ] } ], "source": [ "# Now we compute a Laplace transform\n", "x, s = var('x, s');\n", "print(sin(x).laplace(x,s))\n", "print((1/(s^2 + 1)).inverse_laplace(s,x))" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{a^{n + 1} - 1}{a - 1}\n", "\\end{math}" ], "text/plain": [ "(a^(n + 1) - 1)/(a - 1)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}2^{n}\n", "\\end{math}" ], "text/plain": [ "2^n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Sage can calculate some symbolic sums\n", "var('a k n')\n", "show(sum(a^k,k,0,n))\n", "show(sum(binomial(n,k), k, 0, n))" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}-\\frac{1}{a - 1}\n", "\\end{math}" ], "text/plain": [ "-1/(a - 1)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# You can use the assume to command to put restrictions on variables\n", "# This can be useful for infinite series\n", "# Just running sum(a^k,k,0,infinity) throws a \"ValueError\" -- need to *assume* |a|<1\n", "assume(abs(a)<1)\n", "show(sum(a^k,k,0,infinity))" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "False\n" ] } ], "source": [ "# Assumptions stay with variables until cleared using forget\n", "# Run this cell directly after the previous cell\n", "print(bool(a<1)) # Test if a < 1, under assumption abs(a) < 1\n", "forget(abs(a)<1)\n", "print(bool(a<1)) # Test if a < 1, under no assumptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 3: Mathematical and Algebraic Objects (rings and fields, polynomials, and power series)\n", "\n", "Working over the symbolic ring should be familiar anyone with experience in the Maple and Mathematica computer algebra packages. However, the separation of Sage variables from symbolic variables allows Sage great flexibility for defining and working with mathematical objects. In this section we discuss the different mathematical domains supported in Sage and how to define and work with mathematical objects." ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "# Reset all variables\n", "reset()" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Symbolic Ring\n", "Integer Ring\n", "Rational Field\n", "Algebraic Field\n", "Finite Field in z2 of size 3^2\n", "Algebraic Real Field\n", "Ring of integers modulo 10\n", "Real Field with 10 bits of precision\n", "Complex Field with 10 bits of precision\n" ] } ], "source": [ "# We will define mathematical objects using various algebraic domains (rings, fields, vector spaces, etc.)\n", "# Here are a few common domains and their default shortcuts \n", "# (Note: it is possible to accidentically overwrite the default shortcuts!)\n", "\n", "print(SR) # Symbolic Ring\n", "print(ZZ) # Integers (ZZ is default shortcut for IntegerRing())\n", "print(QQ) # Rational numbers (QQ is default shortcut for RationalField())\n", "print(QQbar) # Algebraic numbers (QQbar is default shortcut for AlgebraicField())\n", "print(GF(9)) # GF(p^k) is the finite field with p^k elements (GF(p^k) is default shortcut for FiniteField(p^k))\n", "print(AA) # Real algebraic numbers (AA is default shortcut for AlgebraicRealField())\n", "print(IntegerModRing(10)) # IntegerModRing(n) = ring Z/nZ\n", "print(RealField(10)) # RealField(k) is real floating points with k bits of precision (RR is a shortcut for RealField(53))\n", "print(ComplexField(10)) # ComplexField(k) is complex floating points with k bits of precision (CC is a shortcut for ComplexField(53))" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Univariate Polynomial Ring in t over Rational Field\n", "t^2 + 1\n", "Univariate Polynomial Ring in VAR over Rational Field\n", "VAR^2 + 1\n" ] } ], "source": [ "# Domains can be defined recursively (we do not get fully into user defined domains here)\n", "# Here we set the Sage variable t to point to the symbolic variable \"t\" generating a poly ring over the rationals\n", "# The notation \"A.\" tells Sage to make the Sage variable t equal the symbolic variable \"t\"\n", "# Running A = QQ['t'] would make A the same field, but would not update the Sage variable t\n", "A. = QQ['t']\n", "print(A)\n", "print(t^2+1)\n", "\n", "# The Sage variable representing the symbolic variable doesn't need to match the symbolic variable\n", "B. = QQ['VAR']\n", "print(B)\n", "print(v^2+1)\n", "# print(VAR) # running this would give an error as the Sage variable VAR is undefined" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Power Series Ring in w over Ring of integers modulo 10\n", "Full MatrixSpace of 3 by 2 dense matrices over Ring of integers modulo 10\n" ] } ], "source": [ "# Two more examples, defining power series and matrix rings\n", "R = IntegerModRing(10)\n", "print(R[['w']])\n", "print(MatrixSpace(R,3,2))" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Univariate Polynomial Ring in t over Rational Field\n", "True\n", "True\n", "t\n", "Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X)\n", "x^5 + x^2\n", "[x^3, x^3 + 1, x^3 + x, x^3 + x + 1, x^3 + x^2, x^3 + x^2 + 1, x^3 + x^2 + x, x^3 + x^2 + x + 1]\n" ] } ], "source": [ "# These domains are themselves objects in Sage, and have associated functions\n", "# If no symbolic variable name is specified, the Sage variable is used for the symbolic variable by default\n", "A. = QQ[]\n", "B. = GF(2)[]\n", "print(A)\n", "print(A.is_commutative())\n", "print(A.is_euclidean_domain())\n", "print(A.gen())\n", "print(B)\n", "print(B.random_element(5))\n", "print(list(B.polynomials(of_degree=3)))" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Univariate Polynomial Ring in t over Rational Field\n", "(t - 1) * (t + 1) * (t^2 - 2)\n", "[(1, 1), (-1, 1)]\n", "\n" ] } ], "source": [ "# If t is the generator of the field QQ[t] then Sage knows polynomial expressions in t live in QQ[t]\n", "# Functions in these expressions, such as roots, factor, etc. can now work over the appropriate domain \n", "# Inappropriate functions or expressions in t will now give an error\n", "# By default, the roots command returns a list of the form (root, multiplicity)\n", "A. = QQ[]\n", "pol = (t^2 - 1)*(t^2-2)\n", "print(parent(pol))\n", "print(pol.factor())\n", "print(pol.roots())\n", "print(pol.factor) # We see the factor method uses the FLINT package" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The polynomial t^4 - 3*t^2 + 2 is no longer defined by entering (t^2 - 1)*(t^2-2): this now evaluates to 6\n", "The problem is that the variable t is a constant, now lying in [Integer Ring]\n", "Now the variable t is back to lying in [Univariate Polynomial Ring in t over Rational Field]\n", "True\n" ] } ], "source": [ "# Here we accidentally set the Sage variable t to a constant, instead of the Symbolic variable \"t\"\n", "# This does not affect our polynomial pol, but hinders defining new polynomials\n", "# We can fix this by setting the Sage variable back to the generator of our field A = QQ[t]\n", "A. = QQ[]; pol = (t^2 - 1)*(t^2-2) # Define t symbolically as above\n", "\n", "t = 2\n", "print(\"The polynomial {} is no longer defined by entering (t^2 - 1)*(t^2-2): this now evaluates to {}\".format(pol,(t^2 - 1)*(t^2-2)))\n", "print(\"The problem is that the variable t is a constant, now lying in [{}]\".format(parent(t)))\n", "\n", "# Set Sage variable t back to symbolic variable \"t\" generating the ring A\n", "t = A.gen()\n", "print(\"Now the variable t is back to lying in [{}]\".format(parent(t)))\n", "print(A == parent(t))" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "We have the constants a = 1/2 (over Rational Field), b = 1/2 (over Algebraic Field), and c = 0.500000000000000 (over Real Field with 53 bits of precision)\n", "Although they look the same, pol = t^2 - 1 lives in Univariate Polynomial Ring in t over Integer Ring while pol2 = t^2 - 1 lives in Univariate Polynomial Ring in t over Rational Field\n" ] } ], "source": [ "# The domain of an object can be explicitly defined by \"casting\" into the domain (when possible)\n", "a = QQ(1/2) # Cast 1/2 into the field of rational numbers\n", "b = QQbar(1/2) # Cast 1/2 into the field of real algebraic numbers\n", "c = RR(1/2) # Cast 1/2 into the field of real floating point numbers to 53 bits of precision\n", "print(\"We have the constants a = {} (over {}), b = {} (over {}), and c = {} (over {})\".format(a,parent(a),b,parent(b),c,parent(c)))\n", "\n", "A = ZZ['t']\n", "pol = A('t^2-1') # Define a polynomial by casting from a string to ZZ[t]\n", "pol2 = QQ['t'](pol) # Cast pol from ZZ[t] into QQ[t]\n", "print(\"Although they look the same, pol = {} lives in {} while pol2 = {} lives in {}\".format(pol,parent(pol),pol2,parent(pol2)))" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "print(GF(3)(1/2)) # This conversion is allowed, because 2 has an inverse in Z/3Z\n", "#print(GF(3)(1/3)) # Uncomment and run this code to get an error, because 3 is not invertible in Z/3Z" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "p = -5*t^5 - 2*t^4 + 9*t^3 - 5*t^2 + t is an element of Univariate Polynomial Ring in t over Integer Ring\n", "q = t^5 + t^4 + t^2 + t is an element of Univariate Polynomial Ring in t over Finite Field of size 3\n", "r = -5*T^5 - 2*T^4 + 9*T^3 - 5*T^2 + T is an element of Univariate Polynomial Ring in T over Integer Ring\n" ] } ], "source": [ "# change_ring and change_variable_name can also be used to change parameters of a polynomial ring\n", "R = ZZ['t']\n", "p = R.random_element(5)\n", "print(\"p = {} is an element of {}\".format(p, parent(p)))\n", "q = p.change_ring(GF(3))\n", "print(\"q = {} is an element of {}\".format(q, parent(q)))\n", "r = p.change_variable_name('T')\n", "print(\"r = {} is an element of {}\".format(r, parent(r)))" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The value -1176 obtained from the polynomial -5*t^5 - 2*t^4 + 9*t^3 - 5*t^2 + t lies in Integer Ring\n", "The value 0 obtained from the polynomial -5*t^5 - 2*t^4 + 9*t^3 - 5*t^2 + t lies in Finite Field of size 3\n", "The following matrix, obtained from the polynomial -5*t^5 - 2*t^4 + 9*t^3 - 5*t^2 + t, lies in Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3\n" ] }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rr}\n", "1 & 0 \\\\\n", "0 & 1\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[1 0]\n", "[0 1]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Can substitute values that can be interpreted as elements of an A-algebra into polys of A[x]\n", "sub1 = p.subs(3)\n", "sub2 = q.subs(t=3) # Variable can be explicitly specified (optional for univariate polys)\n", "sub3 = q.subs(matrix([[1,2],[3,4]]))\n", "\n", "print(\"The value {} obtained from the polynomial {} lies in {}\".format(sub1,p,parent(sub1)))\n", "print(\"The value {} obtained from the polynomial {} lies in {}\".format(sub2,p,parent(sub2)))\n", "print(\"The following matrix, obtained from the polynomial {}, lies in {}\".format(p,parent(sub3)))\n", "show(sub3)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "25*t^5 + 4*t^4 + 81*t^3 + 25*t^2 + t" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Can apply functions to all coefficients\n", "p.map_coefficients(lambda z: z^2)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "[0, 1, -5, 9, -2]\n" ] } ], "source": [ "# Coefficients of polynomials can be accessed similar to arrays\n", "print(p[1])\n", "print([p[k] for k in range(5)])" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x^2 - 2\n", "(x + 3) * (x + 4)\n", "(x - sqrt2) * (x + sqrt2)\n", "\n" ] } ], "source": [ "# Factorization works over different coefficient rings\n", "A. = QQ[]\n", "p = QQ['x'](x^2-2)\n", "print(p.factor()) # Factor over the rationals\n", "print(p.change_ring(GF(7)).factor()) # Factor in finite field of order 7\n", "print(p.change_ring(QQ[sqrt(2)]).factor()) # Factor over Q adjoin the square-root of 2\n", "\n", "# Factorizations lie in a Factorization class, which allows \n", "# one to access the elements of the factorization, the powers, etc.\n", "print(parent(p.factor())) " ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The roots of x^4 - x^3 - x^2 + 2*x - 1 in QQ are [1] \n", "\n", "The roots of x^4 - x^3 - x^2 + 2*x - 1 in QQbar are [-1.324717957244746?, 1, 0.6623589786223730? - 0.5622795120623013?*I, 0.6623589786223730? + 0.5622795120623013?*I] \n", "\n", "For instance, the algebraic number -1.324717957244746? is a root of x^4 - x^3 - x^2 + 2*x - 1, encoded as an element of Algebraic Field\n", "The algebraic number -1.324717957244746? is stored exactly. Its minimal polynomial is x^3 - x + 1 and a numeric approximation to 100 bits is -1.3247179572447460259609088545\n" ] } ], "source": [ "# The roots method works the same way\n", "# Over the field of algebraic numbers, the solutions are stored exactly.\n", "# Algebraic numbers (among other special classes of numbers) are denoted by a \"?\" at the end of a decimal\n", "p = QQ['x']((x-1)*(x^3-x+1))\n", "print(\"The roots of {} in QQ are {} \\n\".format(p,p.roots(multiplicities=False)))\n", "\n", "rts = p.roots(QQbar,multiplicities=False)\n", "print(\"The roots of {} in QQbar are {} \\n\".format(p,rts))\n", "\n", "r1 = rts[0]\n", "print(\"For instance, the algebraic number {} is a root of {}, encoded as an element of {}\".format(r1,p,parent(r1)))\n", "print(\"The algebraic number {} is stored exactly. Its minimal polynomial is {} and a numeric approximation to 100 bits is {}\".format(r1,r1.minpoly(),r1.n(100)))" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [], "source": [ "############################\n", "# Short Exercise: Type \"r1.\" and press to the methods available for an algebraic number.\n", "# Run a few of these methods (look at the corresponding help pages, if necessary)\n", "############################\n" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The Galois group of x^3 - x + 1 is the group Finitely presented group < a, b | a^2, b^3, (b*a)^2 > \n", "\n", "x^3 - x + 1 has the factorization (x - alpha) * (x^2 + alpha*x + alpha^2 - 1) in Number Field in alpha with defining polynomial x^3 - x + 1 \n", "\n", "A splitting field of x^3 - x + 1 is Number Field in beta with defining polynomial x^6 + 3*x^5 + 19*x^4 + 35*x^3 + 127*x^2 + 73*x + 271 \n", "\n", "Over this splitting field, x^3 - x + 1 has factorization (x - 1/69*beta^5 - 2/69*beta^4 - 13/69*beta^3 - 2/69*beta^2 - 12/23*beta + 100/69) * (x + 3/575*beta^5 + 3/575*beta^4 + 1/575*beta^3 - 147/575*beta^2 - 6/23*beta - 906/575) * (x + 16/1725*beta^5 + 41/1725*beta^4 + 14/75*beta^3 + 491/1725*beta^2 + 18/23*beta + 218/1725)\n" ] } ], "source": [ "# The structure of the roots can be explored further using Sage's methods\n", "p = QQ['x'](x^3-x+1)\n", "gal = p.galois_group()\n", "print(\"The Galois group of {} is the group {} \\n\".format(p,gal.as_finitely_presented_group()))\n", "\n", "K. = NumberField(x^3-x+1) # Number field where alpha is a root of x^3-x+1\n", "print(\"{} has the factorization {} in {} \\n\".format(p,p.change_ring(K).factor(),K))\n", "\n", "L. = p.splitting_field() # Splitting field of p\n", "print(\"A splitting field of {} is {} \\n\".format(p,L))\n", "print(\"Over this splitting field, {} has factorization {}\".format(p,p.change_ring(L).factor()))" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2 + x + 6*x^2 + O(x^3)\n", "1 + x + 4*x^2 + O(x^3)\n", "The precision of [1 + 2*x + 3*x^2 + O(x^3)] + [1 - x + 3*x^2 + O(x^4)] is 3\n" ] } ], "source": [ "# The ring of power series works up to some precision, and automatically keeps track of precision\n", "R. = QQ[[]]\n", "f = 1 + 2*x + 3*x^2 + O(x^3)\n", "g = 1 - x + 3*x^2 + O(x^4)\n", "print(f+g)\n", "print(f*g)\n", "print(\"The precision of [{}] + [{}] is {}\".format(f,g,(f+g).prec()))" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n", "True\n", "True\n" ] } ], "source": [ "# Be careful with equality of formal series!!\n", "# Equality only tested up to lowest precision\n", "print(1+2*x == 1+x+O(x^2))\n", "print(1+x == 1+x+O(x^2))\n", "print(1+x+x^3 == 1+x+O(x^2))\n", "print(0 == O(x^2))" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}1 + \\frac{1}{2}x - \\frac{1}{8}x^{2} + \\frac{1}{16}x^{3} - \\frac{5}{128}x^{4} + \\frac{7}{256}x^{5} - \\frac{21}{1024}x^{6} + \\frac{33}{2048}x^{7} - \\frac{429}{32768}x^{8} + \\frac{715}{65536}x^{9} + O(x^{10})\n", "\\end{math}" ], "text/plain": [ "1 + 1/2*x - 1/8*x^2 + 1/16*x^3 - 5/128*x^4 + 7/256*x^5 - 21/1024*x^6 + 33/2048*x^7 - 429/32768*x^8 + 715/65536*x^9 + O(x^10)" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}3x - \\frac{9}{2}x^{3} + \\frac{81}{40}x^{5} - \\frac{243}{560}x^{7} + \\frac{243}{4480}x^{9} + O(x^{10})\n", "\\end{math}" ], "text/plain": [ "3*x - 9/2*x^3 + 81/40*x^5 - 243/560*x^7 + 243/4480*x^9 + O(x^10)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Sometimes series can be calculated by a direct conversion from the symbolic ring\n", "show(sqrt(1+x) + O(x^10))\n", "show(sin(x+2*x) + O(x^10))" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Principal ideal (x^2 + 1) of Univariate Polynomial Ring in x over Rational Field\n", "The generator of the ring [Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1] is xbar\n", "In K, xbar^2 = -1\n" ] } ], "source": [ "# Ideals and quotient rings can also be defined\n", "R. = QQ[]\n", "J = R.ideal(x^2+1)\n", "print(J)\n", "\n", "K = R.quo(J)\n", "xb = K(x) # Make xb the image of x in the residue ring K\n", "print(\"The generator of the ring [{}] is {}\".format(K,xb))\n", "print(\"In K, xbar^2 = {}\".format(xb^2))" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "With the lift command, we can recover the variable x in Univariate Polynomial Ring in x over Rational Field (which maps to xbar in the residue ring)\n" ] } ], "source": [ "# The lift command gives an element back in the original ring\n", "# (the unique equivalent polynomial of degree less than the modulus)\n", "# After lifting, one can do things like substitute values which are not available in quotient rings\n", "print(\"With the lift command, we can recover the variable {} in {} (which maps to xbar in the residue ring)\".format(xb.lift(),parent(xb.lift())))" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.414213562373095048801688724210?\n", "[1.4142135623730950488016887242091 .. 1.4142135623730950488016887242108]\n", "1.4142135623730950488016887242\n", "100\n", "(1.4142135623730950488016887242, 1.4142135623730950488016887243)\n" ] } ], "source": [ "# Sage also supports interval arithmetic (RealIntervalField(n) = field with 100 bits of precision)\n", "R = RealIntervalField(100)\n", "a = R(sqrt(2))\n", "print(a)\n", "print(a.str(style='brackets'))\n", "print(a.center())\n", "print(a.precision())\n", "print(a.endpoints())" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-1.324717957244746?\n", "[-1.3247179572447460259609088544787 .. -1.3247179572447460259609088544770]\n" ] } ], "source": [ "# Define an algebraic number, then get an interval of precision 100 bits containing the algebraic number\n", "r1 = QQbar['x'](x^3-x+1).roots(multiplicities=False)[0] # Select the first root over the algebraic numbers\n", "print(r1)\n", "print(r1.interval(RealIntervalField(100)).str(style='brackets'))" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.4142135623730949 .. 1.7320508075688775]\n", "Real Interval Field with 53 bits of precision\n", "[-3.2162452993532733e-16 .. 1.2246467991473533e-16]\n", "True\n" ] } ], "source": [ "# RIF = RealIntervalField(53)\n", "print(RIF(sqrt(2),sqrt(3)).str(style='brackets')) # Defines interval\n", "print(RIF)\n", "si = sin(RIF(pi))\n", "print(si.str(style='brackets'))\n", "print(si.contains_zero())" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3.14159265358979323846264338328 +/- 2.25e-30]" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# An alternative to interval arithmetic is ball arithmetic\n", "# ComplexIntervalField(n) and ComplexBallField(n) are the analogous domains for complex numbers\n", "RealBallField(100)(pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 4: Linear Algebra" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Full MatrixSpace of 3 by 4 dense matrices over Integer Ring\n" ] }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "0 & 0 & 0 & 0 \\\\\n", "0 & 0 & 0 & 0 \\\\\n", "0 & 0 & 0 & 0\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[0 0 0 0]\n", "[0 0 0 0]\n", "[0 0 0 0]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "1 & 2 & 3 & 4 \\\\\n", "5 & 6 & 7 & 8 \\\\\n", "9 & 10 & 11 & 12\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[ 1 2 3 4]\n", "[ 5 6 7 8]\n", "[ 9 10 11 12]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# MatrixSpace defines the spaces of matrices\n", "MS = MatrixSpace(ZZ,3,4)\n", "print(MS)\n", "show(MS()) # Zero matrix\n", "A = MS([1,2,3,4,5,6,7,8,9,10,11,12]) # Since the dimension is fixed, a matrix can be entered as a vector\n", "show(A)" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "1 & 2 & 3 & 4 \\\\\n", "5 & 6 & 7 & 8 \\\\\n", "9 & 10 & 11 & 12\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[ 1 2 3 4]\n", "[ 5 6 7 8]\n", "[ 9 10 11 12]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# A matrix can also be defined as a list of rows\n", "show(MS([[1,2,3,4],[5,6,7,8],[9,10,11,12]]))" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}7\n", "\\end{math}" ], "text/plain": [ "7" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "9 & 10 & 11 & 12\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[ 9 10 11 12]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rr}\n", "3 & 4 \\\\\n", "7 & 8\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[3 4]\n", "[7 8]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", "1 & 2 & 2 & 1 \\\\\n", "0 & 0 & 2 & 0\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[1 0 0 0]\n", "[1 2 2 1]\n", "[0 0 2 0]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Elements are accessed similar to arrays\n", "show(A[1,2]) # Access single entry\n", "show(A[-1,:]) # Acess a row (-1 = final row/column index and \":\" = all rows/columns)\n", "show(A[0:2,2:]) # Acess a submatrix (notation \"k:\" goes from index k to final index)\n", "show(MS.change_ring(GF(3)).random_element())" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|The|\\phantom{\\verb!x!}\\verb|matrices|\\phantom{\\verb!x!}\\verb|\t| \\left(\\begin{array}{rr}\n", "1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right) \\verb|and|\\phantom{\\verb!x!}\\verb|\t| \\left(\\begin{array}{rr}\n", "0 & 1 \\\\\n", "1 & 0\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|generate|\\phantom{\\verb!x!}\\verb|the|\\phantom{\\verb!x!}\\verb|matrix|\\phantom{\\verb!x!}\\verb|group|\\phantom{\\verb!x!}\\verb|\t| \\left\\langle \\left(\\begin{array}{rr}\n", "1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right), \\left(\\begin{array}{rr}\n", "0 & 1 \\\\\n", "1 & 0\n", "\\end{array}\\right) \\right\\rangle \\phantom{\\verb!x!}\\verb|over|\\phantom{\\verb!x!}\\verb|\t| \\Bold{F}_{11}\n", "\\end{math}" ], "text/plain": [ "'The matrices \\t' [1 2]\n", "[3 4] 'and \\t' [0 1]\n", "[1 0] ' generate the matrix group \\t' Matrix group over Finite Field of size 11 with 2 generators (\n", "[1 2] [0 1]\n", "[3 4], [1 0]\n", ") ' over \\t' Finite Field of size 11" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "This group contains the identity\n" ] } ], "source": [ "# Matrix groups can also be defined\n", "A = matrix(GF(11), 2, 2, [1,2,3,4])\n", "B = matrix(GF(11), [[0,1],[1,0]])\n", "MG = MatrixGroup([A,B])\n", "show(\"The matrices \\t\", A, \"and \\t\", B, \" generate the matrix group \\t\", MG, \" over \\t\", MG.base_ring());\n", "if identity_matrix(GF(11),2) in MG:\n", " print(\"This group contains the identity\")\n", "else:\n", " print(\"This group does not contain the identity\")" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rr}\n", "-1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|and\t| \\left(\\begin{array}{rr}\n", "-1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right) \\verb|are|\\phantom{\\verb!x!}\\verb|both|\\phantom{\\verb!x!}\\verb|changed,|\\phantom{\\verb!x!}\\verb|but\t| \\left(\\begin{array}{rr}\n", "1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|is|\\phantom{\\verb!x!}\\verb|not|\n", "\\end{math}" ], "text/plain": [ "[-1 2]\n", "[ 3 4] ' and\\t' [-1 2]\n", "[ 3 4] 'are both changed, but\\t' [1 2]\n", "[3 4] ' is not'" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Just like lists, matrices are stored as pointers -- need to use B = copy(A) to have independent copy\n", "A = Matrix(ZZ,[[1,2],[3,4]])\n", "B = A\n", "C = copy(A)\n", "A[0,0]=-1\n", "show(A,\" and\\t\",B,\"are both changed, but\\t\",C,\" is not\")" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|We|\\phantom{\\verb!x!}\\verb|define|\\phantom{\\verb!x!}\\verb|the|\\phantom{\\verb!x!}\\verb|matrix|\\phantom{\\verb!x!}\\verb|A|\\phantom{\\verb!x!}\\verb|=| \\left(\\begin{array}{rrrrr}\n", "0 & 1 & 2 & 3 & 4 \\\\\n", "5 & 6 & 7 & 8 & 9 \\\\\n", "10 & 11 & 12 & 13 & 14\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|(over|\\phantom{\\verb!x!}\\verb|the|\\phantom{\\verb!x!}\\verb|rational|\\phantom{\\verb!x!}\\verb|numbers)|\n", "\\end{math}" ], "text/plain": [ "'We define the matrix A = ' [ 0 1 2 3 4]\n", "[ 5 6 7 8 9]\n", "[10 11 12 13 14] ' (over the rational numbers)'" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|The|\\phantom{\\verb!x!}\\verb|image|\\phantom{\\verb!x!}\\verb|of|\\phantom{\\verb!x!}\\verb|A|\\phantom{\\verb!x!}\\verb|is|\\phantom{\\verb!x!}\\verb|\t| \\mathrm{RowSpan}_{\\Bold{Q}}\\left(\\begin{array}{rrrrr}\n", "1 & 0 & -1 & -2 & -3 \\\\\n", "0 & 1 & 2 & 3 & 4\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "'The image of A is \\t' Vector space of degree 5 and dimension 2 over Rational Field\n", "Basis matrix:\n", "[ 1 0 -1 -2 -3]\n", "[ 0 1 2 3 4]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|The|\\phantom{\\verb!x!}\\verb|right|\\phantom{\\verb!x!}\\verb|kernel|\\phantom{\\verb!x!}\\verb|of|\\phantom{\\verb!x!}\\verb|A|\\phantom{\\verb!x!}\\verb|is|\\phantom{\\verb!x!}\\verb|\t| \\mathrm{RowSpan}_{\\Bold{Q}}\\left(\\begin{array}{rrrrr}\n", "1 & 0 & 0 & -4 & 3 \\\\\n", "0 & 1 & 0 & -3 & 2 \\\\\n", "0 & 0 & 1 & -2 & 1\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "'The right kernel of A is \\t' Vector space of degree 5 and dimension 3 over Rational Field\n", "Basis matrix:\n", "[ 1 0 0 -4 3]\n", "[ 0 1 0 -3 2]\n", "[ 0 0 1 -2 1]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# One can also construct the image and kernel of a matrix\n", "A = matrix(QQ,3,5,list(range(15)))\n", "im = A.image()\n", "ker = A.right_kernel()\n", "show(\"We define the matrix A = \",A, \" (over the rational numbers)\")\n", "show(\"The image of A is \\t\",im)\n", "show(\"The right kernel of A is \\t\",ker)" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{RowSpan}_{\\ZZ/3\\ZZ}\\left(\\begin{array}{rrrrr}\n", "1 & 0 & 2 & 1 & 0 \\\\\n", "0 & 1 & 2 & 0 & 1\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "Vector space of degree 5 and dimension 2 over Ring of integers modulo 3\n", "Basis matrix:\n", "[1 0 2 1 0]\n", "[0 1 2 0 1]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\mathrm{RowSpan}_{\\ZZ/3\\ZZ}\\left(\\begin{array}{rrrrr}\n", "1 & 0 & 0 & 2 & 0 \\\\\n", "0 & 1 & 0 & 0 & 2 \\\\\n", "0 & 0 & 1 & 1 & 1\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "Vector space of degree 5 and dimension 3 over Ring of integers modulo 3\n", "Basis matrix:\n", "[1 0 0 2 0]\n", "[0 1 0 0 2]\n", "[0 0 1 1 1]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Same thing over a different ring\n", "B = A.change_ring(GF(3))\n", "show(B.image())\n", "show(B.right_kernel())" ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-0.3722813232690144?, 5.372281323269015?]\n", "[1, 1]\n" ] } ], "source": [ "# We can compute the eigenvalues of a matrix (over the appropriate field)\n", "A = matrix(QQ,[[1,2],[3,4]])\n", "B = matrix(GF(3),[[1,2],[3,4]])\n", "print(A.eigenvalues())\n", "print(B.eigenvalues())" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(-0.3722813232690144?, [(1, -0.6861406616345072?)], 1), (5.372281323269015?, [(1, 2.186140661634508?)], 1)]\n" ] } ], "source": [ "# And get the eigenvector corresponding to each eigenvector\n", "# (we get a list of the form (e,V,n) where e is the eigenvalue, V is a list of eigenvectors forming a\n", "# basis for the corresponding right eigenspace, and n is the algebraic multiplicity of the eigenvalue)\n", "print(A.eigenvectors_right())" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-0.3722813232690144?\n", "x^2 - 5*x - 2\n" ] } ], "source": [ "# As noted above, algebraic numbers are stored exactly, even if only the decimal expansion is printed\n", "eig1 = A.eigenvalues()[0]\n", "print(eig1)\n", "print(eig1.minpoly())" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The Jordan Form exists over the field\n", "Number Field in a with defining polynomial x^2 - 5*x - 2 with a = -0.3722813232690144?\n", "The Jordan Form implies\n" ] }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rr}\n", "1 & 1 \\\\\n", "-\\frac{1}{2} a + 2 & \\frac{1}{2} a - \\frac{1}{2}\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|times\t| \\left(\\begin{array}{rr}\n", "-a + 5 & 0 \\\\\n", "0 & a\n", "\\end{array}\\right) \\phantom{\\verb!x!}\\verb|times\t| \\left(\\begin{array}{rr}\n", "\\frac{1}{11} a + \\frac{3}{11} & -\\frac{4}{33} a + \\frac{10}{33} \\\\\n", "-\\frac{1}{11} a + \\frac{8}{11} & \\frac{4}{33} a - \\frac{10}{33}\n", "\\end{array}\\right) \\verb|equals|\\phantom{\\verb!x!}\\verb|A=| \\left(\\begin{array}{rr}\n", "1 & 2 \\\\\n", "3 & 4\n", "\\end{array}\\right)\n", "\\end{math}" ], "text/plain": [ "[ 1 1]\n", "[ -1/2*a + 2 1/2*a - 1/2] ' times\\t' [-a + 5 0]\n", "[ 0 a] ' times\\t' [ 1/11*a + 3/11 -4/33*a + 10/33]\n", "[ -1/11*a + 8/11 4/33*a - 10/33] 'equals A=' [1 2]\n", "[3 4]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|where|\\phantom{\\verb!x!}\\verb|a|\\phantom{\\verb!x!}\\verb|is|\\phantom{\\verb!x!}\\verb|the|\\phantom{\\verb!x!}\\verb|algebraic|\\phantom{\\verb!x!}\\verb|number|\\phantom{\\verb!x!}\\verb|defined|\\phantom{\\verb!x!}\\verb|by\t| x^{2} - 5 x - 2 \\verb|=0|\\phantom{\\verb!x!}\\verb|approximately|\\phantom{\\verb!x!}\\verb|equal|\\phantom{\\verb!x!}\\verb|to| -0.37228\n", "\\end{math}" ], "text/plain": [ "'where a is the algebraic number defined by\\t' x^2 - 5*x - 2 '=0 approximately equal to' -0.37228" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Over appropriate rings, one can compute the Diagonalization, Jordan Form, etc. of a matrix\n", "# A.jordan_form() # running this results in \"RuntimeError: Some eigenvalue does not exist in Rational Field.\"\n", "# We must extend the rational numbers to compute the Jordan Form\n", "R = QQ[eig1] # Define the extension of QQ by adding an eigenvalue of A\n", "print(\"The Jordan Form exists over the field\")\n", "print(R)\n", "\n", "A = A.change_ring(R)\n", "M1,M2 = A.jordan_form(transformation=True, subdivide=False) # Now we can diagonalize (using the Jordan form command)\n", "\n", "print(\"The Jordan Form implies\")\n", "show(M2,\" times\\t\", M1,\" times\\t\",M2.inverse(),\"equals A=\",M2*M1*M2.inverse())\n", "show(\"where a is the algebraic number defined by\\t\", R.gen().minpoly(), \"=0 approximately equal to\", R.gen().n(20))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 5: Polynomial System Solving" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [], "source": [ "# Reset all variables\n", "reset()" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}x^{2} + y + z \\phantom{\\verb!x!}\\verb|is|\\phantom{\\verb!x!}\\verb|a|\\phantom{\\verb!x!}\\verb|polynomial|\\phantom{\\verb!x!}\\verb|in|\\phantom{\\verb!x!}\\verb|the|\\phantom{\\verb!x!}\\verb|ring| \\Bold{Q}[x, y, z]\n", "\\end{math}" ], "text/plain": [ "x^2 + y + z ' is a polynomial in the ring ' Multivariate Polynomial Ring in x, y, z over Rational Field" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Multivariate polynomial rings are defined similarly to univariate rings\n", "R. = QQ['x,y,z']\n", "p = x^2+y+z\n", "show(p,\" is a polynomial in the ring \", parent(p))" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "x^2*y + x*y^2\n", "y^2*x + y*x^2\n", "True\n" ] } ], "source": [ "# The order of variables matters when defining a ring\n", "A = QQ['x,y']\n", "B = QQ['y,x']\n", "print(A==B)\n", "print(A(x*y^2+y*x^2))\n", "print(B(x*y^2+y*x^2))\n", "print(A(x*y^2+y*x^2) == B(x*y^2+y*x^2))" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "#################################################################\n", "# EXERCISE: Define a polynomial ring R over the rational numbers whose variables \n", "# are xk for all primes k less than 100 (so the variables are x2,x3,x5,...)\n", "# HINT: First make the string str = \"x2,x3,x5,...\" then use R = QQ[str]\n", "#################################################################\n" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}-x_{1} + x_{0} + 3 y_{1} + y_{0}\n", "\\end{math}" ], "text/plain": [ "-x_1 + x_0 + 3*y_1 + y_0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}[x_{\\ast}, y_{\\ast}]\n", "\\end{math}" ], "text/plain": [ "Infinite polynomial ring in x, y over Integer Ring" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}[x_{1}, x_{0}, y_{1}, y_{0}]\n", "\\end{math}" ], "text/plain": [ "Multivariate Polynomial Ring in x_1, x_0, y_1, y_0 over Integer Ring" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}[x_{5}, x_{4}, x_{3}, x_{2}, x_{1}, x_{0}, y_{5}, y_{4}, y_{3}, y_{2}, y_{1}, y_{0}]\n", "\\end{math}" ], "text/plain": [ "Multivariate Polynomial Ring in x_5, x_4, x_3, x_2, x_1, x_0, y_5, y_4, y_3, y_2, y_1, y_0 over Integer Ring" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\Bold{Z}[x_{5}, x_{4}, x_{3}, x_{2}, x_{1}, x_{0}, y_{5}, y_{4}, y_{3}, y_{2}, y_{1}, y_{0}]\n", "\\end{math}" ], "text/plain": [ "Multivariate Polynomial Ring in x_5, x_4, x_3, x_2, x_1, x_0, y_5, y_4, y_3, y_2, y_1, y_0 over Integer Ring" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# One can use an arbitrarily large number of variables, extending the number of variables as necessary\n", "# (note that running this cell a second time will give a different behaviour than the first run)\n", "R. = InfinitePolynomialRing(ZZ, order='lex')\n", "p = x[0]+y[0]-x[1]+3*y[1]\n", "show(p)\n", "show(parent(p))\n", "show(parent(p.polynomial()))\n", "show(parent((p + x[5]).polynomial()))\n", "show(parent(p.polynomial()))" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "2\n" ] } ], "source": [ "# Coefficients of a polynomial can be specified by a monomial or a list of exponents\n", "R. = QQ[]\n", "p = (x+y)^2\n", "print(p[x*y])\n", "print(p[1,1])" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Ideal (x + y, x^3*y + x*z^2, x^2*y + z) of Multivariate Polynomial Ring in x, y, z over Rational Field" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Ideals can be defined using the ideal method of a polynomial ring\n", "R. = QQ[]\n", "J = R.ideal(x+y,x*z^2+y*x^3,z+x^2*y)\n", "J" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The dimension of the ideal is 0\n", "The solutions over QQ are [{z: 0, y: 0, x: 0}, {z: 1, y: -1, x: 1}]\n", "The solutions over the algebraic closure are [{z: 0, y: 0, x: 0}, {z: 1, y: -1, x: 1}, {z: 1, y: 0.50000000000000000? - 0.866025403784439?*I, x: -0.50000000000000000? + 0.866025403784439?*I}, {z: 1, y: 0.50000000000000000? + 0.866025403784439?*I, x: -0.50000000000000000? - 0.866025403784439?*I}]\n" ] } ], "source": [ "# The typical algebraic geometry methods can be applied to ideals and the corresponding varieties\n", "# Can find solutions for zero-dimensional ideals\n", "print(\"The dimension of the ideal is {}\".format(J.dimension()))\n", "print(\"The solutions over QQ are {}\".format(J.variety())) # Solutions over the defining field QQ\n", "print(\"The solutions over the algebraic closure are {}\".format(J.variety(QQbar))) # Solutions over the algebraic closure QQbar" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{z: 1, y: 0.50000000000000000? + 0.866025403784439?*I, x: -0.50000000000000000? - 0.866025403784439?*I}\n", "-0.50000000000000000? - 0.866025403784439?*I\n" ] } ], "source": [ "# To access elements of a variety, the user needs to define variables for poly ring over the correct field\n", "(xx, yy, zz) = QQbar['x,y,z'].gens()\n", "sbs = J.variety(QQbar)[-1] # Get an element of J as a dictionary of substitutions\n", "print(sbs)\n", "# \"x.subs(sbs)\" gives an error as \"x\" not variable for QQbar -- it is used above for QQ[x,y,z]\n", "# We instead substitute into the Sage variable xx which points to the generator \"x\" of QQbar[x,y,z]\n", "print(xx.subs(sbs))" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[x, x - 1, x^2 + x + 1, x^2 + x + 1]\n" ] } ], "source": [ "# Here we print the minimal polynomials of the x coordinates of the elements in the variety\n", "print([ pt[xx].minpoly() for pt in J.variety(QQbar) ])" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Quotient of Multivariate Polynomial Ring in x, y, z over Rational Field by the ideal (x + y, x^3*y + x*z^2, x^2*y + z)\n", "[1, -ybar, ybar^2, zbar, -ybar*zbar]\n" ] } ], "source": [ "# We can also define multivariate quotient rings\n", "xbar = R.quo(J)(x)\n", "print(parent(xbar))\n", "print([xbar^k for k in range(5)])" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[-72/67*x^2 - 72/67*x*y - 48/67*y^2 - 18/67*x - 36/67*y + 1, -72/67*y + 9/67, 24/67*y^3 - 9/67*x^2 - 18/67*y^2 + 72/67*x - 5/67*y + 18/67]" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# q.lift(J) writes q as a polynomial combination of the elements of J\n", "# Note we use R(1) to specify the constant 1 in R (instead of the integer 1, as is the default)\n", "R(1).lift(ideal(1-x*y+y^2, x^3-y^2, x+2*y))" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(x + y, y z - y, y^{3} + z\\right)\\Bold{Q}[x, y, z]\n", "\\end{math}" ], "text/plain": [ "Ideal (x + y, y*z - y, y^3 + z) of Multivariate Polynomial Ring in x, y, z over Rational Field" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/latex": [ "\\begin{math}\n", "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(z - 1, x + y, y^{2} - y + 1\\right)\\Bold{Q}[x, y, z], \\left(z - 1, y + 1, x - 1\\right)\\Bold{Q}[x, y, z], \\left(x + y, z^{2}, y z, y^{3} + z\\right)\\Bold{Q}[x, y, z]\\right]\n", "\\end{math}" ], "text/plain": [ "[Ideal (z - 1, x + y, y^2 - y + 1) of Multivariate Polynomial Ring in x, y, z over Rational Field,\n", " Ideal (z - 1, y + 1, x - 1) of Multivariate Polynomial Ring in x, y, z over Rational Field,\n", " Ideal (x + y, z^2, y*z, y^3 + z) of Multivariate Polynomial Ring in x, y, z over Rational Field]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Can find radicals, primary decompositions, etc.\n", "show(J.radical())\n", "show(J.primary_decomposition())" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Ideal (z^3 - z^2, y*z^2 - y*z, y^3 + z) of Multivariate Polynomial Ring in x, y, z over Rational Field" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Can get elimination ideals\n", "J.elimination_ideal(x)" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "y^2*z - y^2 + 1\n" ] } ], "source": [ "# Can reduce via repeated division algorithm \n", "# (output depends on the order of the factors unless J is a Grobner Basis)\n", "p = x^5-y^2+1\n", "print(p.reduce(J))" ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[y^3 + z, y*z^2 - y*z, z^3 - z^2, x + y]\n" ] } ], "source": [ "# Can compute Grobner Bases\n", "# Monomial term orders include lex, invlex, deglex, and degrevlex\n", "GB = J.groebner_basis()\n", "print(GB)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Exercise 1) \n", "An efficient method of computing high powers $x^N$ for an element $x$ of a ring is to use *binary powering*, through the formula\n", "\\begin{equation} \n", "x^N = \n", "\\begin{cases} \\left(x^{N/2}\\right)^2 &: \\text{ $N$ even} \\\\\n", "x \\cdot \\left(x^{(N-1)/2}\\right)^2 &: \\text{ $N$ odd}\n", "\\end{cases}\n", "\\end{equation}\n", "Write a recursive function `bin_pow(x,n)` which takes an element $x$ from a ring (your implementation should not care which) and a natural number $n$ and returns $x^n$ in approximately $\\log_2 n$ multiplications using binary powering." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Exercise 2)\n", "Recall again the Fibonacci numbers defined by the recursive formula $f_n = f_{n-1} + f_{n-2}$ for $n \\geq 2$ and $f_0=f_1=1$. Show that the $N$th Fibonacci number $f_N$ can be recovered from the matrix product\n", "\\begin{equation} \n", "\\begin{pmatrix} 1 & 1 \\\\ 1 & 0 \\end{pmatrix}^N \\; \\begin{pmatrix} 1 \\\\ 1 \\end{pmatrix}\n", "\\end{equation}\n", "Using the `bin_pow` function from Exercise 1, find the one millionth Fibonacci number. If $M$ is the matrix being raised to the $N$th power, the command `print(timeit('bin_pow(M,1000000)'))` will measure the time it takes Sage to run this command. How does the time change if $M$ is defined over different rings (for instance, as a matrix over the integers, over the rationals, and over algebraic numbers)?\n", "\n", "*Note: Because Sage has built-in optimizations for powering a matrix, using your binary powering function may not be faster than running `M^N`. However, your function should only be slower by a small constant amount of time (not changing much, if at all, with $N$).*" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Exercise 3)\n", "Create the field extension of the rational numbers obtained by adjoining an eigenvalue of the matrix $M$ from Exercise 2. Working over this field extension, diagonalize $M$. Deduce an explicit expression for the $N$th Fibonacci number." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Exercise 4)\n", "The fastest method of determining terms in a linearly recurrent sequence, such as the Fibonacci numbers, is not to use matrix powers (although this is much faster than naively using the recurrence). Instead, the idea is to compute powers of elements in a residue class ring defined by such a recurrence.\n", "\n", "Skipping the details of why this works, define the residue class ring of polynomials in $x$ with rational coefficients modulo the polynomial $x^2-x-1$. Let $\\overline{x}$ be the image of $x$ in this ring. Use Sage to compute the powers $\\overline{x},\\overline{x}^2,\\dots,\\overline{x}^5$. Can you see how to recover the $N$th Fibonacci number from $\\overline{x}^N$? \n", "\n", "Use your `bin_pow` method from Exercise 1 to compute the one millionth Fibonacci number using this approach. Use the `timeit` command described above to compare the amount of time it takes to run `bin_pow(xbar,1000000)`, `bin_pow(M,1000000)`, and `M^1000000`, where `xbar` denotes $\\overline{x}$ and $M$ is the matrix from Exercise 2. Which is fastest?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (Exercise 5)\n", "A *simple random walk* of length $n$ on the lattice $\\mathbb{Z}^2$ is a sequence of $n$ steps from the set $\\{(-1,0),(1,0),(0,-1),(0,1)\\}$ picked uniformly at random. Create a function which takes a natural number $n$ and returns a plot displaying a simple random walk of length $n$. Create a plot overlaying the result of 100 random walks of length 100, each of a distinct colour." ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 1, 1, 1, 2, 1, 2, 3, 4, 3]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "Graphics object consisting of 1 graphics primitive" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The following functions will be useful.\n", "\n", "# The choice function picks a random element of a list. For instance,\n", "print([choice([1,2,3,4]) for k in range(10)])\n", "\n", "# The line command plots a line from a list of points. For instance,\n", "show(line([[0,0],[0,1],[2,2]], color = \"black\", thickness=2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.1", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }