[NumCS] Add numpy, scipy and sympy quick overview

This commit is contained in:
2026-01-13 11:22:34 +01:00
parent ca0cab49a5
commit a7eb412c84
10 changed files with 226 additions and 1 deletions

Binary file not shown.

View File

@@ -109,6 +109,17 @@ We have also taken some explanations and code examples from the slides of our TA
\hlhref{https://n.ethz.ch/~muellerni/courses/numcs25.php}{here}. (Link will be updated if we are to get a new website link from him, as n.ethz.ch is down now)
% TODO: Update this when n.ethz is taken offline completely
A few things to be familiar with for the exam to be quicker at solving exercises:
\begin{itemize}
\item The script. You do not have to know basically anything by heart, so knowing where to find things in the script quickly (and knowing quirks of naming in the script)
will make you much quicker. When searching, always use as short of a keyword as possible while not having hundreds of results.
\item Be aware that some things might not be called the same way they are in the script in the exercises.
If you don't find it immediately, go to the appropriate section in the script (using the index in the PDF reader (that is likely PDF.js, Firefox's PDF reader))
and manually search for it there.
\item Get familiar with the concepts that \texttt{NumPy} uses (i.e. how to do slicing, etc). See section \ref{sec:python} for an overview over some of the concepts.
\item Learn the basics of \texttt{Sympy}, as that will spare you having to do integrals. See section \ref{sec:sympy} for an introduction to \texttt{Sympy}.
\end{itemize}
% ────────────────────────────────────────────────────────────────────
% ╭────────────────────────────────────────────────╮
@@ -200,5 +211,12 @@ We have also taken some explanations and code examples from the slides of our TA
\input{parts/05_curve-fitting/02_non-linear/02_gauss-newton.tex}
\input{parts/05_curve-fitting/02_non-linear/03_further-methods.tex}
\newsection
\section{Introduction to Python}
\label{sec:python}
\input{parts/06_python/00_intro.tex}
\input{parts/06_python/01_numpy.tex}
\input{parts/06_python/02_scipy.tex}
\input{parts/06_python/03_sympy.tex}
\end{document}

View File

@@ -0,0 +1,75 @@
Python is a high-level dynamically and strongly typed, multi-paradigm, interpreted programming language.
Its syntax might remind you of pseudocode, which allows very quick writing, but lacks some control that other lower level programming languages might offer.
Be aware that Python likes to call things differently (\texttt{try ... except} for example instead of \texttt{try ... catch} or \texttt{True, False} instead of \texttt{true, false}).
\subsection{Basics}
\subsubsection{Variables}
While Python supports many different paradigms (thus making it multi-paradigm), Python still is first and foremost an object oriented programming language and all variables
are just references to objects.
What this means is that the variables aren't \textit{technically} conventional variables, but rather pointers and whenever you reassign a value,
the object is actually deleted and a new object is created in its place and the variable's reference is updated. This is one of the reasons as to why
Python is so slow.
Assigning and initializing variables uses the same syntax and you cannot have unassigned variables:
\begin{code}{python}
x # This will not work
x = 1 # Notice that there is no type annotated (Python is dynamically typed)
x = 10 # Assign another value to x
x = "Hello World" # TypeError (Python is strongly typed)
arr = [] # Creates an empty list. They are dynamically sized
d = {} # Creates an empty dict (Dictionary)
arr_list = [ "Hello", "World", 1 ] # Can contain multiple different elements
\end{code}
Python supports the same data types as most other programming languages,
but gives some of them funny names (\texttt{bool}, \texttt{int}, \texttt{float}, \texttt{str}, \texttt{List}, \texttt{Dict} (\texttt{Map} in Java),
\texttt{None} (\texttt{void} in basically all other languages))
To cast a type in python, the basic types are callable, i.e. to cast an \texttt{int} to a \texttt{str}, do \texttt{str(my\_int)}
\subsubsection{Operations}
Python uses the normal operators for basic arithmetic operations, however be aware that Python implicitly casts \texttt{int} to \texttt{float} when dividing.
To do integer division use the \texttt{a // b} syntax. For exponentiation, Python supports the \texttt{a ** b} syntax (which computes $a^b$).
Increment and decrement operators are not supported, however \texttt{+=}, etc are supported.
\subsubsection{Control flow}
Python uses indents (that are consistent, i.e. always use \texttt{n} spaces or a tab character) to indicate blocks.
You cannot use curly braces. In other ways though, Python is fairly lenient, i.e. you are allowed to write parenthesis around the if statement's condition
\begin{code}{python}
# Can also use range(start, stop, step) for a traditional for-loop.
# Parameters start and step can be both (or just one of them) omitted.
for i in iterable:
print(i)
for i, val in enumerate(iterable): # Get index and value (or key and value)
print(i, val)
while True:
break # Break statement to exit loop
if x > 1: # All blocks start with :
print(1)
elif x > 0:
print(2)
else:
print(3)
\end{code}
\subsubsection{Imports}
Python has multiple ways of importing other libraries and from your own files.
Your own imports are always relative to the run file (i.e. not to the current file, but the root file of either the library or your program).
\begin{code}{python}
import lib.mylib # Local import from file lib/mylib.py
import numpy # Import numpy. Access numpy functions using numpy.<method>(...)
import numpy as np # Alias numpy to np. Access using np.<method>(...)
from numpy import array # Only import array method from numpy. Call using array(...)
# The below is the biggest Python sin. DO NOT DO THIS!
from numpy import * # Wildcard import (import all functions from the library as <method>(...))
\end{code}
What you should always refrain from doing is a wildcard import. Every function from that library is then imported directly and can be called using \texttt{<method>(...)}.
Thus, if two libraries have a function that has the same name, your program will stop working, thus always either import a specific function, or better still,
use the options on line 2 or 3 for library imports, as it is also much easier for other people to understand where the function is defined.

View File

@@ -0,0 +1,103 @@
\newpage
\subsection{Numpy}
Numpy is a library that, according to its website, is ``The fundamental package for scientific computing with Python''.
If you prefer to read an online guide, the \hlhref{https://numpy.org/doc/stable/user/quickstart.html}{official quick start guide}\ is excellent.
\subsubsection{Arrays}
The heart of numpy is the \texttt{numpy.ndarray} class (it has the alias \texttt{numpy.array}). As the name would imply, it can be any dimension you would like.
The most important attributes for this course are: \texttt{shape} (returns a tuple that indicates the number of elements for each dimension),
\texttt{dtype} (indicates the data type of elements in the array),
\texttt{ndim} (the number of dimensions, equal to \texttt{len(shape)})
To create an array, we can use a few functions:
\drmvspace
\begin{multicols}{2}
\begin{itemize}[noitemsep]
\item \texttt{np.array([...])}
\item \texttt{np.zeros(shape)}
\item \texttt{np.zeros\_like(arr)}
\item \texttt{np.ones(shape)}
\item \texttt{np.ones\_like(arr)}
\item \texttt{np.empty\_like(arr)}
\item \texttt{np.arange(start, stop, step)}
\item \texttt{np.linspace(start, stop, num\_el)}
\item \texttt{np.logspace(start, stop, num\_el)}
\item \texttt{np.eye(N, M)} (\texttt{N} is rows, \texttt{M} is cols)
\item \texttt{np.identity(N, M)}
\item \texttt{np.fromfunction(f, (dim1, \dots))}
\end{itemize}
\end{multicols}
\dnrmvspace
To use complex numbers, we can write \texttt{a + b * 1.j}
Another useful method is \texttt{np.meshgrid(x, y, \dots)}, which returns a coordinate grid
and treats the input vectors as \texttt{x}, \texttt{y}, etc coordinates of point \texttt{i}.
Arrays aren't usually copied, but you get a view. The \texttt{reshape} method below is an example of a case where you get a shallow copy (that still technically is a view).
The values are still in the same object, but you get access to it in a different shape.
To deep copy an array (i.e. create a new array), use \texttt{arr.copy()}
\subsubsection{Operations}
The same basic operations that Python supports are also supported by numpy, though they are executed on each element.
\begin{itemize}[noitemsep]
\item You can subtract a number from an ndarray
\item You can subtract an ndarray from another ndarray (vector, matrix, ... difference)
\item To compute a matrix product (or matrix-vector product), you can do \texttt{A @ B} or \texttt{np.dot(A, B)}
\item \texttt{arr.sum()} sums up all elements and \texttt{arr.sum(axis=n)} sums up all elements on that axis (0 is column, 1 is row)
\item \texttt{arr.cumsum()} computes the cumulative sum (i.e. each element in the output is the sum of all preceding elements). You can also use the axis argument again.
\item \texttt{np.exp}, \texttt{np.sqrt}, etc operate element-wise on the array
\item \texttt{np.where(condition, arr\_true, arr\_false)} returns a numpy array where if \texttt{condition} is true,
element \texttt{i} is chosen from \texttt{arr\_true}, else from \texttt{arr\_false}
\end{itemize}
A useful trick to create a mask is to use \texttt{a < b} (or any other comparison), as that will return an array of booleans.
For piecewise interpolation, a useful method is \texttt{np.searchsorted(arr.flat, vals\_insert, side='right')}, where \texttt{vals\_insert} are the values to be inserted
and the \texttt{side} argument indicates on which side of the match they are to be inserted.
For that though, the array needs to be sorted, for which we can use \texttt{np.argsort(arr, axis=-1)}.
This will return the indices in the order that would sort the array along the given axis. If axis is unspecified, \texttt{-1} is used.
To use these indices to sort an array, we can simply use \texttt{arr[np.argsort(arr)]}.
Slicing and indexing works just as in Python (assume \texttt{a} is a numpy array):
\begin{code}{python}
a = np.arange(10)
print(a[2]) # Outputs 2 (third element)
print(a[-1]) # Outputs 9 (last element)
print(a[-2]) # Outputs 8 (2nd to last element)
print(a[2:5]) # Outputs [2, 3, 4] (elements 2, 3, and 4)
print(a[2:5:-1]) # Outputs [4, 3, 2] (reversed)
print(a[::-1]) # Reverses the array
\end{code}
So, the basic syntax for slicing is \texttt{a[start : stop : step]} and any of them can be omitted, though the corresponding colons cannot be omitted if you omit start.
We can also iterate over a numpy array normally (the iterator variable will be the \texttt{i}-th element of the outermost array of the numpy array).
To iterate over all elements of the array (i.e. the actual data values), we can use \texttt{arr.flat} to get a view (similar to a reference, not copied) that has
length that corresponds to the sum of all elements of \texttt{arr.shape}.
For \texttt{n}-d arrays, we can use \texttt{a[0, 1]} to access element \texttt{a[0][1]}, which is more efficient.
\subsubsection{Shape manipulation}
We can reshape an array by using \texttt{arr.reshape(dim1, dim2, \dots)}. This however returns the array with modified shape,
whereas \texttt{arr.resize((dim1, dim2, \dots))} modifies the array directly (notice that here we have to pass a tuple!)
To get a one-dimensional array, we can use \texttt{arr.ravel()}, after which the array looks the same
as \texttt{arr.flat}, but the change is permanent
\fhlc{Cyan}{Stacking arrays}
\texttt{np.vstack((a, b))} adds array \texttt{b}'s elements to array \texttt{a} (i.e. stacks along \texttt{axis=0}).
\texttt{np.hstack((a, b))} adds array \texttt{b}'s elements to the inner arrays of \texttt{a} (i.e. stacks along \texttt{axis=1}).
\texttt{np.concatenate((a, b, \dots), axis=n)} does as the above, but applies it to axis \texttt{n}
\fhlc{Cyan}{Splitting arrays}
\texttt{np.hsplit(a, count)} splits \texttt{a} into \texttt{count} arrays (along \texttt{axis=0})
\texttt{np.vsplit(a, count)} splits \texttt{a} into \texttt{count} arrays (along \texttt{axis=1})
\texttt{np.array\_split(a, count, axis=n)} splits \texttt{a} into \texttt{count} arrays (along \texttt{axis=n})

View File

@@ -0,0 +1,8 @@
\newpage
\subsection{Scipy}
Scipy is a library that, according to its website, provides ``Fundamental algorithms for scientific computing in Python''.
In this course it is primarily used for cases where Numpy either does not have an implementation or SciPy's implementation is faster.
Scipy needs Numpy arrays as inputs in most cases, thus not requiring any additional syntax.
You can find the scipy reference docs \hlhref{https://docs.scipy.org/doc/scipy/reference/index.html}{here}

View File

@@ -0,0 +1,15 @@
import sympy as sp
a, b = (0, 1);
x, y = sp.symbols("x, y") # Create sympy symbols
f = x**2 + 3 * x - 2 # Create your function
# In the below, for 1D differentiation, we can omit the symbol and just use sp.diff(f)
df = sp.diff(f, x) # Add more arguments for derivatives in other variables
F = sp.integrate(f, x) # Integrates the function analytically in x
F = sp.integrate(f, (x, a, b)) # Indefinite integral in x in interval [a, b]
lambda_f = sp.lambdify(x, F) # Creates a lambda function of F in variable x
lambda_f = sp.lambdify([x, y], F) # Creates a lambda function of F in variables x and y
roots = sp.roots(f) # Computes the roots of function f analytically
sp.hermite_poly(5) # Creates hermite poly of degree 5
sp.chebyshevt_poly(5) # Creates chebychev T (first kind) poly of degree 5
sp.chebyshevu_poly(5) # Creates chebychev U (second kind) poly of degree 5

View File

@@ -0,0 +1,6 @@
\subsection{Sympy}
\label{sec:sympy}
Sympy can be used to do symbolic operations, i.e. similar to what we would do in Analysis or the like.
You usually want to follow something like the below code:
\inputcode{python}{parts/06_python/03_sympy-ex.py}