Non-teaching aspects of teaching at University of Calgary

I’ve been a math postdoc at University of Calgary for two years now, and I’ll be here for at least one more year. The teaching environment is very pleasant, and the resources are abundant. Nonetheless, there are a few non-teaching aspects of it that bothers me. The way that the teaching is handled in the mathematics department for postdocs is that we are hired as a sessional instructors, with a no strings attached for the teaching. A course is assigned to us, with a fixed number for the pay. There are no benefits coming with it, and no pension associated to it. However, after 1 year of being a sessional instructor we can apply for $200 reimbursement in professional development activities.

During the first semester that I was here, I didn’t have a teaching duty, but I was offered to teach a course for extra pay, which I took it. However, by the end of semester I realized that I haven’t been paid for my teaching at all. It turned out that it was an error of the accounting personnel of the department which hadn’t put me on payroll (teaching salary is separate from my postdoc salary). Eventually, I got a lump sum for my Fall semester teaching in the following February. A year later when filing for taxes, I realized that getting paid all of it in February wasn’t a good idea, since it resulted in my paying about an extra $1000 in taxes for that year. The case isn’t resolved yet. Well, to be honest, I still don’t know how to even go after fixing this!

Let me tell you a little about how our department counts teaching. Each “regular” course (whatever that means) in a semester counts as one “half course equivalent”, which means a sessional instructor gets paid about $6250 for teaching it, and it counts as “one” teaching duty for a full time faculty member. It turns out that the department counts teaching, for example, a Calculus 1 course (Math 249 or Math 265) with up to 180 students as 1 “half course equivalent” for the faculty, and up to 240 students as 1.5, and up to 360 students as 2 “half course equivalents”. That is, if you are a full time faculty here with teaching load of 2 for the Fall semester, all you need to do is to teach a Calculus 1 course with 360 students in it. The weird part of it is that you don’t get to know any of these things by default, and I couldn’t find any documents in the department talking about this, maybe for lack of trial!

What I have experienced here as a postdoc (sessional instructor) though, is that all of the courses that I’ve taught with 240 students still counts as 1 “half course equivalent”, that is I get paid about $6250 for it, and also I am supposed to run one of the labs for whatever course I teach. I haven’t had any concerns regarding this so far, until there came up a situation about my teaching duties next year. It all started with a simple confusion, in my postdoc contract I was supposed to be teaching one course as part of my responsibilities. So, as I said above, the way that this is handled is that they reduce my negotiated pay by around $6250 and then hire me as a sessional instructor and then pay that amount to me via a separate series of pay checks. The confusion was that the associate head of teaching of the department thought I am supposed to teach two courses as part of my duties, he then scheduled me for one large section (360 students) of Calculus 1 (Math 265), which my new postdoc supervisor objected, as it will consume too much time from me, hence I won’t be able to spend enough time on my research. After a few emails back and forth between people (I wasn’t involved here) I was told that I will be teaching the large section and get paid for two half course equivalents, and even as an “exception” they’ll drop the lab for me! It sounded like an awesome deal. So I agreed.

Until last week that they sent me the contract to be signed, which said I’m getting paid for one half course equivalent. Upon inquir”es” it turned out that the department has decided that “it is pretty fair” if I teach a large section instead of a small section + lab. I’ll probably take the offer, but it leaved me with this question that why there are such double standards segregating the faculty and sessionals, and why the policies in the department are not transparent.

Advertisements

Feedback – part I

Without much ado here is a book that is changing my life:

51n1xhgd9hl-_sx324_bo1204203200_

And why is it changing my life? Well, the book was introduced to me in a workshop about how to make sense of student comments in regular end-of-semester evaluation forms. So, I started reading the book. The premise of the book is that there are various reasons to get triggered when one receives comments and there are different types of feedback and expecting one type and receiving another type causes some troubles. Then it goes into several examples, and many many details of it and ways to prevent some of them, solve some of them, and avoid some others. I particularly like the book because of its scientific approach to writing, but at the same time being very conversational, and my most favourite part is their examples. They provide tons of examples, many case studies, and several extreme examples.

BUT…

It is changing my life because as I keep reading it, I realize that most of communications and relations in one’s life fall into the same categories that the book describes, and one can follow the same strategies to make the whole experience of communicating with others (at any level and of any sort) much much better. To give you an idea of the big picture of the book, let me mention some of the main things:

One of the things that the book mentions is that when you receive a feedback three things can be triggered:

  1. Truth:
    • It is when you feel like the feedback is not representing the truth. For example, “I couldn’t be rude at that party, because I wasn’t at that party. And my name is not Mike!” This is of course one of their extreme examples that makes the whole thing make a lot of sense and I love it. In a more realistic way, I could get a comment from a student that I don’t have a sense of time! While I go to class 5 minutes early and prepare my slides and the notes, and start right at 10 O’clock to lecture. What the student is saying is not the truth. Well, at least not according to my definition. They go and discuss it in much detail that what happens when we feel the comment about us is not the truth and how we can resolve this. Some of the later chapters of the book are on the different aspects of this trigger.
  2. Relationship:
    • It happens when you expect some other type of point of view. For example, a student can tell that “he wasn’t organized.” and you feel like “after all that work that I put into preparing this class and the schedule that I followed to the minute, and extra problems with solutions that I posted online, you tell me this?”. Or in a different way, you might get a comment that “He knows math but he doesn’t know how to teach it!” And you’ll be like “Who the hell are you to judge my teaching?!” There are a lot to be learnt from the feedback when this gets triggered and the book spends a good amount on this topic.
  3. Identity:
    • It is when you feel like you don’t know who you are, e.g. “Maybe I am a bad teacher after all”, or “What am I doing with my life teaching these courses?” And there are many other things that can be done in this case too.

The book goes on to identify three types of feedback:

  1. Praise:
    • “Good job”, “Awesome teacher”, “Worst instructor ever” etc are examples of praise. It doesn’t have much information in it. It simply says the feedback giver is happy or not with the performance. We all need that at times and some times we receive that feedback.
  2. Coaching:
    • “Give us more time during the class to work on problems”, “provide more examples”, “he talks too fast (i.e. don’t talk too fast)” etc are examples of coaching. They have lots of information in them and usually these what make you grow.
      • If I’m looking for praise and receive coaching instead, I’ll be maaaaaaaaaaaaad! “I’m spending lots of time preparing for this course, don’t tell me I need to use a larger size font on the worksheets!”.
      • If I’m looking for coaching and receive praise instead, I’ll be alright but frustrated as I don’t know where to go next. “OK, the exam I designed was a good exam and covered all the material, but how can I make it more related to practice problems students are doing? how do I make sure that it’s not too much for 2 hours? How would I ask a reasonable question about that topic that I didn’t ask about it?”.
  3. Evaluation:
    • Your salary gets raised, a student sings up for your next class after they had a course with you before, you get fired, your spouse wants a divorce, you get accepted to graduate school. These are examples of evaluation.
      • If I’m looking for praise and I receive evaluation instead, I’ll feel a little lost. “OK, my contract got extended, but am I doing well enough? Are you happy with me?”.
      • If I’m looking for evaluation and I get praised instead, I’ll feel they’re hiding something. “Yeah, I know I’m doing a good job, will you sign my contract for next year or not, though?”.
      • If I’m looking for coaching and receive evaluation instead, it’s just unsettling. “My application for this job got rejected, but you haven’t told me what are the strong and weak points on my portfolio, how do I improve it so that I get the job next year, what are the things that you were looking for ans was lacking in my application?”.
      • If I’m looking for evaluation and I get coaching instead, I won’t care! “Are you gonna hire me or not? I don’t care that I should have gone to that conference!”

Then the book goes into every detail of every aspect of these topics and provides many many beautiful examples, and comes up with strategies to figure out what situation we are in and how to respond to each situation when facing them. I don’t necessarily agree with all of their strategies, and I think on several cases I can do the exact opposite of what they suggest and have a better outcome, but the book is extremely helpful in identifying these situations and classifying them.

If you gave it a try, let me know what you think about it, the whole book, or any of the single details. I’d love to discuss the topics to learn more.

Determinant and Jacobian

Today I started my linear algebra class by motivating the determinant using a little bit of history and applications. In particular I talked about determinant appearing in the change of variables in integration of multivariate functions in calculus:Selection_183.pngThen after the class I noticed that my picture of what happens when we linearize the image wasn’t very clear as I had drawn it. So I decided to take a look at an actual example. The following code takes a function f that maps \mathbb{R}^2 to \mathbb{R}^2 and draws three regions:

  • the unit cube in blue,
  • the image of the unit cube under f in red, and
  • the linearization of the image by Jacobian of f at the origin
def show_linearization(f,n=100):
    # f is a function that maps R^2 to R^2 for example
    # f(x,y) = ((x^2+2*(x+2)*(y+1))/4-1,y^2-(x+1)*y)
    # The output is three areas:
        # the unit cube
        # the image of unit cube under f
        # the linearization of the image using the Jacobian of f at (0,0)
    
    var('x y')
    A = jacobian(f,(x,y))(0,0)
    p = f(0,0)
    domxy = []
    imgxy = []
    jacxy = []
    for i in range(n+1):
        for j in range(n+1):
            domxy.append((i/n,j/n))
            imgxy.append(f(i/n,j/n))
            jacxy.append(p+A*vector([i/n,j/n]))
            
    P = points(domxy,color="blue",aspect_ratio=1, alpha = .3)
    Q = points(imgxy,color="red",aspect_ratio=1, alpha = .3)
    R = points(jacxy,color="green",aspect_ratio=1, alpha = .3)
    
    (P+Q+R).show()

Here is a sample run:

f(x,y) = ((x^2+2*(x+2)*(y+1))/4-1,y^2-(x+1)*y)
show_linearization(f)

and the output is:

tmp_znotfi

I chose the function in a way that f(0,0)=(0,0) for simplicity. Here it is on sage cell server for you to play around with it: link.

What do you think? Any suggestions or comments?

Teaching philosophies

One of the recent workshops I’ve attended here at the Taylor Institute was about developing a teaching philosophy offered by Carol Berenson.The goals of the workshop were

  • to reflect on and articulate our beliefs about teaching and learning and where they come from,
  • to make connections between our beliefs and specific teaching and learning strategies, and
  • prepare a draft of a teaching philosophy.

In short, a learner-centred teaching style has the following key elements in it 1-4:

  1. Actively Engage Learners:
    • Material are stimulating, relevant, and interesting
    • Explain material Clearly
    • Use a variety of methods that encourages active learning
    • Adapt to evolving classroom context
  2. Demonstrate Passion, Empathy, and respect:
    • Show interest in students’ opinions and concerns
    • Understand their diverse talents, needs, prior knowledge, and approach to learning
    • Encourage interaction between students and instructor
    • Share your love of the discipline
  3. Communicate Clear Expectations:
    • Make clear the intended learning outcomes and standards for performance
    • Provide organization, structure, and direction for where the course is going
  4. Encourage Student Independence:
    • Provide opportunities to develop and draw upon personal interests
    • Offer choice in learning processes and modes of assessment
    • Provide timely and developmental feedback on learning
    • Encourage metacognition to promote self-assessment
  5. Create a Teaching and Learning Community:
    • Encourage mutual learning
    • Encourage thoughtful, respectful, and collaborative engagement and dialogue between all members of the classroom community
  6. Use Appropriate Assessment methods:
    • Clearly align assessment methods with intended course outcomes
    • Provide clear criteria for evaluation
    • Emphasize deep learning
    • Scaffold assessments to ensure progressive learnin
  7. Commit to Continuous Improvement:
    • Gather formative and summative feedback on your teaching
    • Practice critical self-reflection
    • Consult scholarly literature on teaching and learning
    • Identify clear goals for strengthening your teaching

One of the things that comes to mind that needs to be added to that list is to evaluate the Impact, we’ve had on students. That is, how do we know our students have “learned”.

In order to reflect on above mentioned aspects of a teaching philosophy in ours, we were asked to complete the following questionnaire. I’d be happy to see your responses if you care to share.

A teaching philosophy is a statement that clearly and logically communicates

  • What your fundamental values and beliefs are about teaching and learning
  • Why you hold these values and beliefs (literature and personal experience)
    • It is becoming more common to cite one or two literature in teaching philosophies
    • In mine, I usually refer to a few people that have great impact on my philosophy including
      • Joseph Stepans on values of different teaching methodologies and importance of misconceptions
      • Gilbert Strang on his approach to teaching linear algebra and what matters most is what students remember eventually
  • How you translate these values and beliefs into your teaching and learning practice within the context of your discipline (contains also reflections on how your evaluate and plan to continue grow your practice)

Teaching philosophies are supposed to be 5-7:

  • 1-2 pages long, single spaced
  • First person, narrative, reflective, authentic voice
  • Grounded in discipline, and avoiding jargon
  • might use a metaphor or critical incident as a way in
  • Can link to scholarly literature (speaks to the why)
  • Demonstrates humility and commitment to on-going growth (one can share their challenges)
  • Paints “your” picture
  • and they are an ever evolving work in progress

A typical flow of a teaching philosophy is that it starts with beliefs (what do you think) and moves into the strategies (what do you do), and mentions the impact (what is the effect of these strategies on learners, self, colleagues), and usually ends with the future goals (how will you improve). The impact can be discussed more in the dossier, which could include comments from students, yourself, and colleagues. In order to collect comments from students one can refer to the evaluation forms that are done at the end of each semester. On top of that I usually ask for one or two feedbacks from students during each semester, which is more tailored to what I have in mind and also can help me modify my strategies during a semester. Here is an example of a mid-semester teaching feedback that I ask students to fill out (please do not fill out this one, but if you have suggestions on how to improve the form itself, the last page of the form is for that purpose and I would appreciate any comments):

In order to organize your thoughts to write a teaching philosophy, you can start by filling out a form like this: selection_174

Here is a PDF file for easier printing: PDF. Maybe fill a few of them and then choose between the best 3. As you are filling them out you might notice that a lot of strategies or impacts bleed into each other. In order to eventually formalize them in terms of a statement there are a few things you can do. One is instead of going by rows, go by columns! Another one is to pick the most important strategy for each key belief and do not repeat it for the other ones. One other issue might be that you have beliefs that you haven’t or can’t implement them in your classes. You can refer to these key believes as future goals.

Taylor institute has several great resources on this topic that can be found here. Most of the information that I’ve written here are in that webpage as well as several great teaching philosophy (real) samples.

Footnotes

  1. Arthur Chickering and Zelda F. Gamson (1987) Seven principles for good practice in undergraduate education. AAHE Bulletin, 39(7) 3-7.
  2. P. Ramsden (2003) Learning to teach in higher education: Thirteen principles for effective university teaching. New York: Routledge.
  3. Maryellen Weimer (2013) Learner-centred teaching: Five key changes to practice. John Wiley & Sons.
  4. Lizzio, Alf, Wilson, Keithia, Simons (2002) University students’ perceptions of the learning environment and academic outcomes: Implications for theory and practice. (Conceptual model for an effective academic environment). Studies in higher education, 27(1) 27-52.
  5. Schonwetter (2002)
  6. Seldin and Seldin (2010)
  7. Kearns and Sullivan (2011)

Step-by-step reduction

One of the things that I always tell my students is to check their solutions when they are done solving a problem. That by itself can mean several things, depending on what the problems is. Of course after solving a system of linear equations, one would plug in the solutions into the original system of equations to see if they are satisfied. The harder part is to come up with a way to check if you’ve done the row-reduction correctly or not. One can easily use Sage to see if the reduced row echelon form is computed correctly. If A is your matrix, just input A.rref() to find the reduced row echelon form of it.

But still sometimes in the case that the answer is wrong, one might get frustrated by not trying to figure out in which step they’ve made an error, or sometimes they might just get stuck. Considering that row-reduction is a time consuming process, it is plausible to assume that some one can easily give up after a few tries. I have found this nice code in Sage that shows step-by-step Gauss-Jordan elimination process, and actually tells you what to do in each step, from here. Then I did a little bit of customization on it. Here is the final version:

# Naive Gaussian reduction
def gauss_method(MATRIX,rescale_leading_entry='Last'):
    """Describe the reduction to echelon form of the given matrix of rationals.

    MATRIX  matrix of rationals   e.g., M = matrix(QQ, [[..], [..], ..])
    rescale_leading_entry='First' make the leading entries to 1's while doing Gaussisan ellimination
    rescale_leading_entry='Last' (Default) make the leading entries to 1's while reducing

    Returns: reduced form.  Side effect: prints steps of reduction.

    """
    M = copy(MATRIX)
    num_rows=M.nrows()
    num_cols=M.ncols()
    show(M.apply_map(lambda t:t.full_simplify()))

    col = 0   # all cols before this are already done
    for row in range(0,num_rows): 
        # ?Need to swap in a nonzero entry from below
        while (col < num_cols
               and M[row][col] == 0): 
            for i in M.nonzero_positions_in_column(col):
                if i > row:
                    print " swap row",row+1,"with row",i+1
                    M.swap_rows(row,i)
                    show(M.apply_map(lambda t:t.full_simplify()))
                    break     
            else:
                col += 1

        if col >= num_cols:
            break

        # Now guaranteed M[row][col] != 0
        if (rescale_leading_entry == 'First'
           and M[row][col] != 1):
            print " take",1/M[row][col],"times row",row+1
            M.rescale_row(row,1/M[row][col])
            show(M.apply_map(lambda t:t.full_simplify()))
            
        for changed_row in range(row+1,num_rows):
            if M[changed_row][col] != 0:
                factor = -1*M[changed_row][col]/M[row][col]
                print " take",factor,"times row",row+1,"plus row",changed_row+1 
                M.add_multiple_of_row(changed_row,row,factor)
                show(M.apply_map(lambda t:t.full_simplify()))
        col +=1

    print "Above is a row echelon form, let's keep cruising to get the reduced row echelon form:\n"
    
    for i in range(num_rows):
        row = num_rows-i-1
        if M[row] != 0:
            for col in range(num_cols):
                if M[row,col] != 0:
                    if M[row,col] != 1:
                        print " take",1/M[row][col],"times row",row+1
                        M.rescale_row(row,1/M[row][col])
                        show(M.apply_map(lambda t:t.full_simplify()))
                    break

            for changed_row in range(row):
                factor = -1 * M[row-1-changed_row,col]
                if factor != 0:
                    print " take", factor,"times row", row+1, "plus row", row-1-changed_row+1
                    M.add_multiple_of_row(row-1-changed_row,row,factor)
                    show(M.apply_map(lambda t:t.full_simplify()))
    return(M.apply_map(lambda t:t.full_simplify()))

And here is a sample run:

M = matrix(SR,[[3,-1,4,6],[0,1,8,0],[-2,1,0,-4]])
gauss_method(M,rescale_leading_entry='First')

And the output looks like this: selection_169

Click here to run it in the sage cell server. Note that the code is implemented to work over rational field since it is being used for pedagogical reasons.

In the comments Jason Grout has added an interactive implementation of the first part of the code:

# Naive Gaussian reduction
@interact
def gauss_method(M=random_matrix(QQ,4,algorithm='echelonizable',rank=3),rescale_leading_entry=False):
    """Describe the reduction to echelon form of the given matrix of rationals.

    M  matrix of rationals   e.g., M = matrix(QQ, [[..], [..], ..])
    rescale_leading_entry=False  boolean  make the leading entries to 1's

    Returns: None.  Side effect: M is reduced.  Note: this is echelon form, 
    not reduced echelon form; this routine does not end the same way as does 
    M.echelon_form().

    """
    num_rows=M.nrows()
    num_cols=M.ncols()
    print M    

    col = 0   # all cols before this are already done
    for row in range(0,num_rows): 
        # ?Need to swap in a nonzero entry from below
        while (col < num_cols                and M[row][col] == 0):              for i in M.nonzero_positions_in_column(col):                 if i > row:
                    print " swap row",row+1,"with row",i+1
                    M.swap_rows(row,i)
                    print M
                    break     
            else:
                col += 1

        if col >= num_cols:
            break

        # Now guaranteed M[row][col] != 0
        if (rescale_leading_entry
           and M[row][col] != 1):
            print " take",1/M[row][col],"times row",row+1
            M.rescale_row(row,1/M[row][col])
            print M
        change_flag=False
        for changed_row in range(row+1,num_rows):
            if M[changed_row][col] != 0:
                change_flag=True
                factor=-1*M[changed_row][col]/M[row][col]
                print " take",factor,"times row",row+1,"plus row",changed_row+1 
                M.add_multiple_of_row(changed_row,row,factor)
        if change_flag:
            print M
        col +=1

One of the uses of this can be to find the inverse of a matrix step by step. For example:

var('a b c d')
A = matrix([[a,b],[c,d]])
R = gauss_method(A.augment(identity_matrix(A.ncols()),subdivide=True))

will give you: selection_170Or you can run it for a generic matrix of size 3 (for some reason it didn’t factor i, so I used letter k instead:)

var('a b c d e f g h i j k l m n o p q r s t u v w x y z')
A = matrix([[a,b,c],[d,e,f],[g,h,k]])
R = gauss_method(A.augment(identity_matrix(A.ncols()),subdivide=True))

The steps are too long, so I’m not going to include a snapshot, if you are interested look at the steps here. But you can check out only the final result by

view(R.subdivision(0,1))

which will give you Selection_171.pngAnd to check if the denominators and the determinant of the matrix have any relations with each other you can multiply by the determinant and simplify:

view((det(A)*R.subdivision(0,1)).apply_map(lambda t:t.full_simplify()))

to get

Selection_172.png

Do you think this can help students?

Generating not-so-much-random matrices

I’ve been using sage for a while now. I’ve also been teaching linear algebra for a few years. One of the problems in teaching linear algebra is coming up with a handful of examples of matrices that can nicely be row-reduced. One way to do this is to start with your “nice” row-reduced matrix and take a few (or many) “nice” elementary matrices and there is your example. So, one might want to code this in sage. I just recently found out that actually sage has such a function built in it. For example,

random_matrix(ZZ,4,5,algorithm='echelonizable',rank=3, upper_bound=7)

will create a random 4 \times 5 matrix with rank 3, integer entries (that’s the ZZ), and entries no bigger than 7, which can “nicely” be turned into rref. So, here it is in sage cell server. I think this is a good thing to share with students so they can practice as many times as they want.

For the same reasons when generating a random matrix to find its inverse, we usually want a matrix with small-ish integer entries such that the inverse also has relatively small integer entries. It is easy to see that for a matrix A with integer entries to have an inverse with integer entries, it is necessary that its determinant is \pm 1. It turns out that it is the sufficient condition too, surprisingly, thanks to Cramer’s rule! Though it might lose some pedagogical purposes, like relating the inverse to the determinant, but here is a code that generates random matrices with integer entries where their inverses also have integer entries:

random_matrix(ZZ,3,algorithm='unimodular',upper_bound=6)

To play around with it in sage cell server click here.

[ Ref: https://blogs.uoregon.edu/math341fa15lipshitz/issue-summary/random-matrices-for-practice ]


The sage documentation says:

Warning: Matrices generated are not uniformly distributed. For
unimodular matrices over finite field this function does not even
generate all of them: for example "Matrix.random(GF(3), 2,
algorithm='unimodular')" never generates "[[2,0],[0,2]]". This
function is made for teaching purposes.

And

Random matrices in echelon form.  The "algorithm='echelon_form'"
keyword, along with a requested number of non-zero rows
("num_pivots") will return a random matrix in echelon form.  When
the base ring is "QQ" the result has integer entries.  Other exact
rings may be also specified.

      sage: A=random_matrix(QQ, 4, 8, algorithm='echelon_form', num_pivots=3); A # random
      [ 1 -5  0 -2  0  1  1 -2]
      [ 0  0  1 -5  0 -3 -1  0]
      [ 0  0  0  0  1  2 -2  1]
      [ 0  0  0  0  0  0  0  0]
      sage: A.base_ring()
      Rational Field
      sage: (A.nrows(), A.ncols())
      (4, 8)
      sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
      True
      sage: A.rank()
      3
      sage: A==A.rref()
      True

For more, see the documentation of the "random_rref_matrix()"
function.  In the notebook or at the Sage command-line, first
execute the following to make this further documentation available:

   from sage.matrix.constructor import random_rref_matrix

Random matrices with predictable echelon forms.  The
"algorithm='echelonizable'" keyword, along with a requested rank
("rank") and optional size control ("upper_bound") will return a
random matrix in echelon form.  When the base ring is "ZZ" or "QQ"
the result has integer entries, whose magnitudes can be limited by
the value of "upper_bound", and the echelon form of the matrix also
has integer entries.  Other exact rings may be also specified, but
there is no notion of controlling the size.  Square matrices of
full rank generated by this function always have determinant one,
and can be constructed with the "unimodular" keyword.

      sage: A=random_matrix(QQ, 4, 8, algorithm='echelonizable', rank=3, upper_bound=60); A # random
      sage: A.base_ring()
      Rational Field
      sage: (A.nrows(), A.ncols())
      (4, 8)
      sage: A in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
      True
      sage: A.rank()
      3
      sage: all([abs(x)<60 for x in A.list()])
      True
      sage: A.rref() in sage.matrix.matrix_space.MatrixSpace(ZZ, 4, 8)
      True

For more, see the documentation of the
"random_echelonizable_matrix()" function.  In the notebook or at
the Sage command-line, first execute the following to make this
further documentation available:

   from sage.matrix.constructor import random_echelonizable_matrix
The "x" and "y" keywords can be used to distribute entries
uniformly. When both are used "x" is the minimum and "y" is one
greater than the maximum.

      sage: random_matrix(ZZ, 4, 8, x=70, y=100)
      [81 82 70 81 78 71 79 94]
      [80 98 89 87 91 94 94 77]
      [86 89 85 92 95 94 72 89]
      [78 80 89 82 94 72 90 92]
If only "x" is given, then it is used as the upper bound of a range
starting at 0.

      sage: random_matrix(ZZ, 5, 5, x=25)
      [20 16  8  3  8]
      [ 8  2  2 14  5]
      [18 18 10 20 11]
      [19 16 17 15  7]
      [ 0 24  3 17 24]
To control the number of nonzero entries, use the "density" keyword
at a value strictly below the default of 1.0.  The "density"
keyword is used to compute the number of entries that will be
nonzero, but the same entry may be selected more than once.  So the
value provided will be an upper bound for the density of the
created matrix.  Note that for a square matrix it is only necessary
to set a single dimension.

      sage: random_matrix(ZZ, 5, x=-10, y=10, density=0.75)
      [-6  1  0  0  0]
      [ 9  0  0  4  1]
      [-6  0  0 -8  0]
      [ 0  4  0  6  0]
      [ 1 -9  0  0 -8]
For a matrix with low density it may be advisable to insist on a
sparse representation, as this representation is not selected
automatically.

      sage: random_matrix(ZZ, 5, 5, density=0.3, sparse=True)
      [ 4  0  0  0 -1]
      [ 0  0  0  0 -7]
      [ 0  0  2  0  0]
      [ 0  0  1  0 -4]
      [ 0  0  0  0  0]
Random rational matrices:
    sage: random_matrix(QQ, 2, 8, num_bound=20, den_bound=4) 
    [ -1/2 6 13 -12 -2/3 -1/4 5 5] 
    [ -9/2 5/3 19 15/2 19/2 20/3 -13/4 0]
Random matrices over other rings.  Several classes of matrices have
specialized "randomize()" methods.  You can locate these with the
Sage command:

      search_def('randomize')

Gershgorin Disks

Gershgorin circle theorem roughly states that the eigenvalues of an n \times n matrix lie inside n circles where i-th circle is centred at A_{i,i} and its radius is the sum of the absolute values of the off-diagonal entries of the i-th row of A. Applying this to A^{\top} implies that the radius of this circles shall be the smaller of the sums for rows and columns. The following Sage code draws the circles for a given matrix.

def Gershgorin(A,evals=False):
    # A is a square matrix
    # Output is the Gershgorin disks of A
    
    from sage.plot.circle import Circle
    from sage.plot.colors import rainbow
    
    n = A.ncols()
    Colors = rainbow(n, 'rgbtuple')
    E = point([])
    
    B = A.transpose()
    R = [(A[i-1,i-1], min(sum( [abs(a) for a in (A[i-1:i]).list()] )-abs(A[i-1,i-1]),sum( [abs(a) for a in (B[i-1:i]).list()] )-abs(B[i-1,i-1]))) for i in range(1,n+1)]
    C = [ circle((real(R[i][0]),imaginary(R[i][0])), R[i][1], color="black") for i in range(n)]
    if evals == True:
        E = point(A.eigenvalues(), color="black", size=30)
    CF = [ circle((real(R[i][0]),imaginary(R[i][0])), R[i][1], rgbcolor=Colors[i], fill=True, alpha=1/n) for i in range(n)] 
    
    (sum(C)+sum(CF)+E).show()

And here is a sample output:

A =  random_matrix(CDF,4)
Gershgorin(A)
sage0

Gershgorin disks for a randomly generated 4\times 4 complex matrix

If you want to see the actual eigenvalues, call the function as below:

Gershgorin(A,evals=True)