.. -*- coding: utf-8 -*- .. linkall .. _prep-quickstart-graphs-and-discrete: Sage Quickstart for Graph Theory and Discrete Mathematics ========================================================= This `Sage <http://www.sagemath.org>`_ quickstart tutorial was developed for the MAA PREP Workshop "Sage: Using Open\-Source Mathematics Software with Undergraduates" (funding provided by NSF DUE 0817071). It is licensed under the Creative Commons Attribution\-ShareAlike 3.0 license (`CC BY\-SA <http://creativecommons.org/licenses/by-sa/3.0/>`_). As computers are discrete and finite, topics from discrete mathematics are natural to implement and use. We'll start with Graph Theory. Graph Theory ------------ The pre\-defined ``graphs`` object provides an abundance of examples. Just tab to see! .. skip :: sage: graphs.[tab] Its companion ``digraphs`` has many built\-in examples as well. Visualizing a graph is similar to plotting functions. :: sage: G = graphs.HeawoodGraph() sage: plot(G) Graphics object consisting of 36 graphics primitives Defining your own graph is easy. One way is the following. - Put a vertex next to a list (recall this concept from the programming tutorial) with a colon, to show its adjacent vertices. For example, to put vertex 4 next to vertices 0 and 2, use ``4:[0,2]``. - Now combine all these in curly braces (in the advanced appendix to the programming tutorial, this is called a *dictionary* ). :: sage: H=Graph({0:[1,2,3], 4:[0,2], 6:[1,2,3,4,5]}) sage: plot(H) Graphics object consisting of 18 graphics primitives Adjacency matrices, other graphs, and similar inputs are also recognized. .. Comment this out for now. There is also a cool Javascript graph editor, due to Radoslav Kirov. Check it out! .. skip :: sage: graph_editor() Graphs have "position" information for location of vertices. There are several different ways to compute a layout, or you can compute your own. Pre\-defined graphs often come with "nice" layouts. :: sage: H.set_pos(H.layout_circular()) sage: plot(H) Graphics object consisting of 18 graphics primitives Vertices can be lots of things, for example the codewords of an error\-correcting code. .. note:: Technical caveat: they need to be "immutable", like Python's tuples. Here we have a matrix over the integers and a matrix of variables as vertices. :: sage: a=matrix([[1,2],[3,4]]) sage: var('x y z w') (x, y, z, w) sage: b=matrix([[x,y],[z,w]]) sage: a.set_immutable() sage: b.set_immutable() sage: K=DiGraph({a:[b]}) sage: show(K, vertex_size=800) Edges can be labeled. :: sage: L=graphs.CycleGraph(5) sage: for edge in L.edges(): ....: u = edge[0] ....: v = edge[1] ....: L.set_edge_label(u, v, u*v) sage: plot(L, edge_labels=True) Graphics object consisting of 16 graphics primitives There are natural connections to other areas of mathematics. Here we compute the automorphism group and eigenvalues of the skeleton of a cube. :: sage: C = graphs.CubeGraph(3) sage: plot(C) Graphics object consisting of 21 graphics primitives :: sage: Aut=C.automorphism_group() sage: print("Order of automorphism group: {}".format(Aut.order())) Order of automorphism group: 48 sage: print("Group: \n{}".format(Aut)) # random Group: Permutation Group with generators [('010','100')('011','101'), ('001','010')('101','110'), ('000','001')('010','011')('100','101')('110','111')] :: sage: C.spectrum() [3, 1, 1, 1, -1, -1, -1, -3] There is a huge amount of LaTeX support for graphs. The following graphic shows an example of what can be done; this is the Heawood graph. .. image:: ../media/heawood-graph-latex.png :align: center Press 'tab' at the next command to see all the available options. .. skip :: sage: sage.graphs.graph_latex.GraphLatex.set_option? More Discrete Mathematics ------------------------- Discrete mathematics is a broad area, and Sage has excellent support for much of it. This is largely due to the "sage\-combinat" group. These developers previously developed for MuPad (as "mupad\-combinat") but switched over to Sage shortly before MuPad was sold. Simple Combinatorics ~~~~~~~~~~~~~~~~~~~~~ Sage can work with basic combinatorial structures like combinations and permutations. :: sage: pets = ['dog', 'cat', 'snake', 'spider'] sage: C=Combinations(pets) sage: C.list() [[], ['dog'], ['cat'], ['snake'], ['spider'], ['dog', 'cat'], ['dog', 'snake'], ['dog', 'spider'], ['cat', 'snake'], ['cat', 'spider'], ['snake', 'spider'], ['dog', 'cat', 'snake'], ['dog', 'cat', 'spider'], ['dog', 'snake', 'spider'], ['cat', 'snake', 'spider'], ['dog', 'cat', 'snake', 'spider']] :: sage: for a, b in Combinations(pets, 2): ....: print("The {} chases the {}.".format(a, b)) The dog chases the cat. The dog chases the snake. The dog chases the spider. The cat chases the snake. The cat chases the spider. The snake chases the spider. :: sage: for pair in Permutations(pets, 2): ....: print(pair) ['dog', 'cat'] ['dog', 'snake'] ['dog', 'spider'] ['cat', 'dog'] ['cat', 'snake'] ['cat', 'spider'] ['snake', 'dog'] ['snake', 'cat'] ['snake', 'spider'] ['spider', 'dog'] ['spider', 'cat'] ['spider', 'snake'] Of course, we often want these for numbers, and these are present as well. Some are familiar: :: sage: Permutations(5).cardinality() 120 Others somewhat less so: :: sage: D = Derangements([1,1,2,2,3,4,5]) sage: D.list()[:5] [[2, 2, 1, 1, 4, 5, 3], [2, 2, 1, 1, 5, 3, 4], [2, 2, 1, 3, 1, 5, 4], [2, 2, 1, 3, 4, 5, 1], [2, 2, 1, 3, 5, 1, 4]] And some somewhat more advanced -- in this case, symmetric polynomials. :: sage: s = SymmetricFunctions(QQ).schur() sage: a = s([2,1]) sage: a.expand(3) x0^2*x1 + x0*x1^2 + x0^2*x2 + 2*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 Various functions related to this are available as well. :: sage: binomial(25,3) 2300 :: sage: multinomial(24,3,5) 589024800 :: sage: falling_factorial(10,4) 5040 Do you recognize this famous identity? :: sage: var('k,n') (k, n) sage: sum(binomial(n,k),k,0,n) 2^n .. _CryptoEd: Cryptography (for education) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is also briefly mentioned in the :doc:`Number theory quickstart <Number-Theory>`. Sage has a number of good pedagogical resources for cryptography. .. skip :: sage: # Two objects to make/use encryption scheme sage: # sage: from sage.crypto.block_cipher.sdes import SimplifiedDES sage: sdes = SimplifiedDES() sage: bin = BinaryStrings() sage: # sage: # Convert English to binary sage: # sage: P = bin.encoding("Encrypt this using S-DES!") sage: print("Binary plaintext: {}\n".format(P)) sage: # sage: # Choose a random key sage: # sage: K = sdes.list_to_string(sdes.random_key()) sage: print("Random key: {}\n".format(K)) sage: # sage: # Encrypt with Simplified DES sage: # sage: C = sdes(P, K, algorithm="encrypt") sage: print("Encrypted: {}\n".format(C)) sage: # sage: # Decrypt for the round-trip sage: # sage: plaintxt = sdes(C, K, algorithm="decrypt") sage: print("Decrypted: {}\n".format(plaintxt)) sage: # sage: # Verify easily sage: # sage: print("Verify encryption/decryption: {}".format(P == plaintxt)) Binary plaintext: 01000101011011100110001101110010011110010111000001110100001000000111010001101000011010010111001100100000011101010111001101101001011011100110011100100000010100110010110101000100010001010101001100100001 Random key: 0100000011 Encrypted: 00100001100001010011000111000110010000011011101011111011100011011111101111110111110010101000010010001101101010101000010011001010100001010111000010001101000011001001111111110100001000010000110001011000 Decrypted: 01000101011011100110001101110010011110010111000001110100001000000111010001101000011010010111001100100000011101010111001101101001011011100110011100100000010100110010110101000100010001010101001100100001 Verify encryption/decryption: True Coding Theory ~~~~~~~~~~~~~~ Here is a brief example of a linear binary code (group code). Start with a generator matrix over :math:`\ZZ/2\ZZ`. :: sage: G = matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0], [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]]) sage: C = LinearCode(G) :: sage: C.is_self_dual() False :: sage: D = C.dual_code() sage: D [7, 3] linear code over GF(2) :: sage: D.basis() [ (1, 0, 1, 0, 1, 0, 1), (0, 1, 1, 0, 0, 1, 1), (0, 0, 0, 1, 1, 1, 1) ] :: sage: D.permutation_automorphism_group() Permutation Group with generators [(4,5)(6,7), (4,6)(5,7), (2,3)(6,7), (2,4)(3,5), (1,2)(5,6)]