Not very satisfactorily to be honest. Here is the stack at Arts et Métiers where I do most of my teaching:
- Some sort of system wide Windows virtual machines administered by the IT service.
- Python, Spyder, and Jupyter are installed via conda along with the standard packages.
- For non-standard packages, either we have to install them locally but they disappear once the session is closed (and thus have to proceed again next time) or we try to convince IT that they are safe and have pedagogical value (not too hard, but sometime they simply have other things to do and it takes a while before the package gets deployed system wide).
Every now and then, we have some students who prefer to do everything on their own laptop and so it gets a bit easier (after an initial phase of troubleshooting).
I like Python, but I don’t think it is a language really suitable for teaching the nitty gritty details of a large class of algorithms. For other things, no problems, and you can prototype things quite rapidly so fair enough. I’ve already talked quite extensively about my point of view here. But I think the Jacobi vs Gauss-Seidel discussion is a nice example of why. It would take a lot of ninja skills in Python to get Jacobi to run twice as fast as Gauss-Seidel and that has nothing to do with how the computer works but everything with the language itself. Now this is out of the way, let me answer your question properly.
How do I teach using Python ? – Well, it kind of depends on the class I’m teaching. What is common throughout the different classes however is that I provide the handouts/homework both as pdf + .py files for the students willing to use Spyder, as well as a Jupyter notebook. Jupyter notebooks can be really cool, but one thing I dislike for teaching is that you really do have to execute them linearly. Very often, students have to implement the algorithm in one cell, and run the validation/benchmark cases in another one. And if it doesn’t work, many of them make changes to the algorithm cell and re-execute directly the validation one without re-running the algorithm one. And they don’t understand why their fix did not work until they realize “ah, I need to re-execute the cell I’ve just changed”. It is not a very big issue, but it does add quite a bit of friction. In that respect, notebooks like Pluto in Julia, or even marimo in Python, who keep a dependency graph of the cells, do a much better job. They do come with their own limitations though in that every output of a function should be treated as immutable otherwise it screws up the dependency graph which also adds some friction.
Regarding the different classes now.
Intro to applied linear algebra – Most of the students enrolled in this class finished high-school two or three years prior, and they often can write very simple programs in Python or Matlab. The core of the class is not so much about algorithms themselves rather than being able to formulate a practical (yet heavily simplified) engineering problem in a way it can be solved using simple linear algebra techniques. The poster child here is the QR factorization because you need very little math background to implement it (just vectors, dot products and norms), so does the backward substitution for solving the upper triangular system. When introducing the algorithm, we do have a small discussion about flops (how many flops for a dot product, for a vector addition, etc?) so that they at least get some intuition about computational complexity. They do have to implement this algorithm themselves at least once, but then we just use scipy.linalg.qr and scipy.linalg.solve_triangular.
Mathematically, the two main types of problems/algorithms we discuss are kmeans and equality-constrained convex quadratic programs (like least-squares or least-norms). There are a surprisingly large number of engineering applications you can tackle with only this: linear optimal control, Kalman filters, certain types of linear system identification techniques, curve fitting, clustering for topic discovery in document analysis, simplified forms of robust linear programs for resource allocation, signal processing and smoothing, etc. So the aim of the course is not so much to teach how to do these optimally every time, but more like “look, all of these different problems can somehow but put in the approximately same form, and if you know QR you can get a working solution”. It may not be the exact formulation, nor the optimal way to solve the problem, but at least it works and so I see it like giving them some street-fighting skills. Also, because it is directly applied to problems they may know or understand the practical relevance of, it gives them some more incentive and motivation to see why they may need at least a working understanding of numerical linear algebra.
Linear optimal control and reduced-order modelling – This more of a math-oriented class, still with quite a lot of linear algebra. It is part of a master program in fluid dynamics, and PhD students can also enroll. Convex quadratic programming and SVD are the two main stars of the show. But because the material is quite dense and we only have 30 hours or so in total, we don’t do any programming session in class, nor discuss the details of the linear algebra algorithms themselves, more like a high-level overview of how to compute things like balanced truncation, or value iteration if that rings any bells. Students do have a project to do by the end of the class, and most of them use Jupyter notebooks for the reporting even though I know many of them actually do the development part using Spyder.
Intro to convex optimization – It is a pretty short course (only 12 hours in class, 18 hours in the computer lab divided in 6 sessions) intended for 2nd year Mechanical Engineering students. Until last year, the class was very algorithm-oriented. Students had to implement gradient descent, conjugate gradient, as well as Newton and Quasi-Newton methods. But also because of the students have little experience with programming, we had to stick to fairly simple problems (up to a dozen variables maybe) and so it was hard to have really interesting problems or show the practical difference between Newton and quasi-Newton. Most of the students there were using Jupyter. I am now fully in charge of this class and was given the opportunity to change the whole syllabus so I am currently leaning toward something like the applied linalg class: focus more on the problem formulation and use specialized libraries like cvxpy to abstract away the algorithmic parts so that we can focus on more concrete and illustrative problems. Students will still have to implement a couple of algorithms themselves to get the gist of it but it’ll no longer be the main subject.
All in all, I think I could make a much better use of Jupyter or even Python to have more interactivity in class than what I’m doing now. But given the types of students I have (not particularly numerical methods oriented nor computationally literate), I think I’m facing two more important problems than “how to best use Python in class”:
-
Most of the students don’t see the point in learning this stuff because “hey, it’s already available in numpy or scipy so why should I bother learning how to implement this stuff?”. Also many of them want to become CFD engineers in companies like Airbus or SAFRAN, and they are like “instead of focusing on the maths of PDE or numerical methods, shouldn’t we actually do more large-scale simulations with ANSYS or StarCCM+ because this is what the market is using and I want to be operational with these tools?” I think both questions are valid from a student perspective and I haven’t really been able to come up with a satisfying answer. The best I can do is something along the lines of “well, being computationally literate can only make you a better engineer” but they don’t really get why until they actually face a major problem in their simulations.
-
The other thing is the widespread usage of LLM for anything. And students have a very good natural understanding of physics: they’ll follow the path of least action. And so, here, I’m actually facing two related problems/questions:
a. “Why should I bother learning this stuff if I can prompt an LLM and get a better solution that I could come up with, and faster? Shouldn’t we actually learn better prompt engineering techniques instead?” Again, very sensible question from a student perspective. And again, not a very satisfactory answer in my opinion: well, if the shit hits the fan, you better know the math and the numerics to understand what went wrong. True enoug, but LLM are getting better and better at this. The other answer is well if an LLM can do this, and if every students learn how to prompt the LLM, what will be your added-value to the company that employs you? Why would they bother keeping you around if you are that replacable? This usually triggers them a bit, but as a teacher and mathematician, definitely not satisfactory either.
b. Because these are intro classes, the problems in the set are fairly simple precisely because students should be able to do it on their own. But because the problems are simple, they can just copy-paste into whatever LLM they use and get a working solution with no effort. And that is very hard on me because I have no idea how to actually test what they’ve learned or not. There is also a very nice essay by Lorena Barba (here) about how using LLM often give the students the illusion of competence.
That’s a pretty long answer, I realize I went a bit off road so sorry about that >.<