Skip to content
antonleykin edited this page Jul 26, 2019 · 11 revisions

Questions & Answers (M2 or SAGE)

Questions (expand to see the answer)

How to install M2 under Windows?

One way is described here. It also should be possible to compile M2 from sources in the LSW (Linux subsystem for Windows)

Can you post an intro M2 tutorial (from Monday)?

Here it is: intro for beginners

Can someone teach me debugging tricks for Sage/M2?

For M2 when developing a package...

i1 : newPackage("BugsPackage", DebuggingMode=>true -* set this option *-)

o1 = BugsPackage

o1 : Package

i2 : export "square"

o2 = {square}

o2 : List

i3 : square = x -> (
         print "Doing some calculations";
         y := doCalculations x;
         print "Done";
         y    
         )

o3 = square

o3 : FunctionClosure

i4 : doCalculations = x -> (
         error "debug me"; -- example of a breakpoint
         x*x*x
         )

o4 = doCalculations

o4 : FunctionClosure

i5 : endPackage

o5 = endPackage

o5 : MethodFunction

i6 : square 3
Doing some calculations
stdio:10:5:(3):[2]: error: debug me

More info: viewHelp "debugging"

How do you determine what the current ring is in M2?

There is no concept of "current ring". A symbol could be currently bound to a variable in one of the rings.

i1 : R1 = QQ[x,y]

o1 = R1

o1 : PolynomialRing

i2 : x

o2 = x

o2 : R1

i3 : R2 = ZZ[x,y,z]

o3 = R2

o3 : PolynomialRing

i4 : x

o4 = x

o4 : R2

i5 : use R1 

o5 = R1

o5 : PolynomialRing

i6 : x

o6 = x

o6 : R1
What is the difference between a `MethodFunction` and a `FunctionClosure`?

For more detailed info about methods type viewHelp "method". The following example highlights some aspects.

i1 : f = x -> x^2

o1 = f

o1 : FunctionClosure

i2 : f 4

o2 = 16

i3 : f(1/2)

     1
o3 = -
     4

o3 : QQ

i4 : f matrix{{1,2},{3,4}}

o4 = | 7  10 |
     | 15 22 |

              2        2
o4 : Matrix ZZ  <--- ZZ

i5 : f matrix{{1,2}}
stdio:1:11:(3):[1]: error: maps not composable

i6 : 
     m = method()

o6 = m

o6 : MethodFunction

i7 : m ZZ := x -> x^2 

o7 = -*Function[stdio:8:11-8:16]*-

o7 : FunctionClosure

i8 : m Matrix := x -> if numcols x === numrows x then x^2 else error "can't square a nonsquare matrix"  

o8 = -*Function[stdio:9:15-9:59]*-

o8 : FunctionClosure

i9 : 
     m(1/2)
stdio:11:1:(3): error: no method found for applying m to:
                   1
     argument   :  - (of class QQ)
                   2

i10 : m matrix{{1,2}}
stdio:9:59:(3):[1]: error: can't square a nonsquare matrix

i11 : methods m

o11 = {0 => (m, Matrix)}
      {1 => (m, ZZ)    }

o11 : NumberedVerticalList

i12 : code methods jacobian

o12 = -- code for method: jacobian(Ideal)
      /Applications/Macaulay2-1.14/share/Macaulay2/Core/matrix1.m2:515:33-515:56: --source code:
      jacobian Ideal := Matrix => (I) -> jacobian generators I
      ---------------------------------
      -- code for method: jacobian(Matrix)
      /Applications/Macaulay2-1.14/share/Macaulay2/Core/matrix.m2:500:34-500:65: --source code:
      jacobian Matrix := Matrix => (m) -> diff(transpose vars ring m, m)
      ---------------------------------
      -- code for method: jacobian(MonomialIdeal)
      /Applications/Macaulay2-1.14/share/Macaulay2/Core/monideal.m2:232:41-232:64: --source code:
      jacobian MonomialIdeal := Matrix => (I) -> jacobian generators I
      ---------------------------------
      -- code for method: jacobian(Ring)
      /Applications/Macaulay2-1.14/share/Macaulay2/Core/matrix.m2:502:32-502:62: --source code:
      jacobian Ring := Matrix => (R) -> jacobian presentation R ** R
Can someone please show me how to use Sage and M2 together?

Here is a M2 interface Jupyter worksheet from the session on Thursday.

(At the moment of writing... if you use CoCalc you need to set SageMath (Development, Py3) as your kernel.)

How do `Dictionary`s work in M2?

Here is the corresponding file from the Thursday session

Other questions answered (partially?) in the sessions

(If you have an answer to a question below, please type it in and move the question to the part above).

  • In Sage-8.8 (well actually, Python3), one cannot compare objects of different type. For example sorted({"a", 1}) will produce an error message in recent versions of Sage (it produced [1, 'a'] in older versions). But sorted was a trick used in doctests to make sure the output was the same across different machines ({'a', 1} might print as {1, 'a'} on some machines and {'a', 1} on others). What is the correct way to do handle this type of doctest?

  • Say I'm writing a package, and I introduce a new type, maybe T = new Type of HashTable. Suppose I have a method that creates an object of Type T with a line like X = new T from hashTable{ ... }, and some of the keys in the HashTable already appear as keys of existing M2 objects (keys like cache or degreeList) but others do not (maybe myNewKey). The package will fail to install if myNewKey is neither exported nor protected, but there are no such complaints about keys called something like cache, which M2 already "recognizes". What's the correct way to handle the different keys for Types of this form ("getter" methods versus exporting)?

  • With the same setup as the above question: If I load the package and make an object X of type T, and if myNewKey is protected, then X#myNewKey will throw an error. I feel like this means there are two symbols, both called myNewKey, but only one of them is a key in the HashTable X. How does M2 keep track of this? I suspect this involves these "dictionaries" but I've never understood the specifics.

  • I'm writing a package and I have a method which takes a module, and stores an additional piece of data in the cache of that module with a line like M#cache#myNewKey = foo. Do I need to export or protect myNewKey in this instance? In practice, I have trouble accessing the value at this key in the cache of M, regardless of whether I export the key and try to access it directly, or if I protect the key and write a method in the package to access it. How should I go about doing this? (this might be the same question as above).

  • I sometimes see warnings about certains symbols being "shadowed" by symbols in other dictionaries, but I neither understand what these warnings mean nor do I know how to mitigate them. Where can I learn about this?

  • If I'm overloading a binary operator like * so that it can be applied to my new type T, do I have any control over the operator's precedence? Or its left/right associativity? Or are these permanent properties of * that cannot be changed? If they can be changed for the overloaded usage, what is the syntax? I've seen the page here but it doesn't tell me if or how I can choose my own parsing precedence.

  • I would like to make a net function for my Type T so that the net of a particular object of type T is the user-specified symbol that refers to the object in question. Similar to how the ring R = QQ[x,y,z] will have net R return R. How does the ring "remember" the symbol R that I chose to refer to it? How can I make my types do this?

  • In a fresh M2 session, if I type AlgebraicSplines, I see that this is a symbol. But if I type Polyhedra, I see that this is a Package. The syntax for loading the splines package is loadPackage "AlgebraicSplines", compared to loadPackage Polyhedra (with no quotes). Trying loadPackage "Polyhedra" seems to do something, but mostly it throws lots of errors. Why are there these two different packages treated differently, and is it important to do one versus the other? How does one make a Package object that M2 knows about at startup, even if it hasn't been loaded yet?

  • I've created a new type T and wrote a net function for it that seems to work fine. In playing with the package, I did something which output a list L consisting of 20 objects of type T, and got the error: --error or time limit reached in conversion of output to net, and the actual output I saw was that 20 objects of L with their full hash tables printed out. But when I then do L / (x -> net x), I see what I expected to see in the first place (and it's plenty fast), so I don't see what this "time limit" problem can be.

  • I'm using objects of type T (T = new Type of HashTable) to index variables. When I look at a list of these variables, it prints nicely because I've defined net T. But when I make a matrix full of these variables, it prints horribly, with the underlying HashTable of each variable printed in full. I think I figured out that this is because I also needed a toString method for T. But I suspect there are many other "standard" methods that T needs that I've omitted. Is there a list somewhere of "methods you should always definitely implement for your new types" ?

  • I have a type T, and I've implemented T ? T. When I take an object X of type T and do X ? X, the output is

o1 = ==

o1 = Keyword

But when I try X == X I get the error no method for binary operator == applied to objects. Can I use my ? to implement ==?