# Defining scalars (as floats, not ints)
= 5.0
a = 4.0
b print("Scalars:", a, b)
Scalars: 5.0 4.0
Julie Butler
Date Created: June 16, 2024
Last Modified: June 17, 2024
Disclaimer: You will not have to do much math by hand in this course, but it is good to know how to do some basic operations and what the terminology means.
A scalar is just a number, and for this section a real number (we will cover imaginary and complex numbers in the next section). Real scalars are the numbers you are use to dealing with in most math courses. Scalars can have a decimal place but can also be whole numbers (called an integer). Additionally, scalars can be greater than zero (which are positive scalars) or less than zero (which are negative scalars), or zero. Examples of scalars are 5, 6.7292, and -8.1.
Scalar arithmetic is the math you are use to doing. There are four basic operations that can be performed on scalars: addition, subtraction, multiplication, and division. Note that the order which you add or subtract numbers is not important, but the order of subtraction and division is important.
As an example, let a = 5 and b = 2. * a + b * a + b = 5 + 2 = 7 * a - b * a - b = 5 - 2 = 3 * b - a * b - a = 2 - 5 = -3 (a-b = -(b-a)) * ab (ab) (The first is implicit multiplication and the second is explicit multiplication) 5(2) = 10 * a/b * a/b = 5/2 = 2.5 * b/a * b/a = 2/5 = 0.4
Consider three scalars: a, b, and c. If the scalars are being acted on by the following mathematical equation, ab + ac, since a is in both terms of the sum, you can factor the a out of both terms. This yields a slightly cleaner version of the term of a(b+c). Here we are using implicit multiplication, it is implied that the a is multiplied by b+c.
The opposite of factorization is distribution. Consider the expression (a+b)(a-c). We can create a simpler form of this expression by distributing the a+b term to each part of the second term. so we have (a+b)(a-c) = a(a+b) -c(a+b). We can then distribute the a and the c to the terms in parentheses. So (a+b)(a-c) = a(a+b) -c(a+b) = aa + ab - ac - bc. Note here that we can write aa as \(a^2\) using exponents. So (a+b)(a-c) = a(a+b) -c(a+b) = aa + ab - ac - bc = \(a^2\) (a+b)(a-c) = a(a+b) -c(a+b) = aa + ab - ac - bc. Note that you can also deal with problems like this using the FOIL method, which stands for first, outer, inner, and last. This makes sure you end up with the correct four final terms after the distribution.
We will start by making sure we can program scalars and perform basic scalar arithmetic in Python. If you want to use another language for your programs in this course, feel free to transfer the below code to the language of your choice.
First we will simply define two scalars as floats (meaning they have a decimal place) instead of ints (short for integers, meaning they do not have a decimal place).
Now we will perform the four basic scalar operations with these two variables.
# Addition, Subtraction, Multiplication, Division
add = a+b
sub = a-b
mul = a*b
div = a/b
print("Scalar Math:", add, sub, mul, div)
Scalar Math: 9.0 1.0 20.0 1.25
Finally, it is important to note that while we use implicit multiplication when we are multiplying a scalar by a term in parentheses, you cannot do that in Python. You must use explicit multiplication, meaning you have to add the “*” to the code to denote multiplication.
A complex number is a number which has both a real part and in imaginary part. A complex number is written as z = a + ib, where a is the real part of the number, b is the imaginary part (not ib, just b), and i is the imaginary number. i is defined as the solution to the equation \(i^2+1=0\) or \(i = \sqrt{-1}\). A number of the form z = ib is called an imaginary number, the presence of the real component makes it a complex number.
As an example, find the real and complex components of the following numbers: * z = 2+3i * The real part is 2 and the imaginary part is 3. * z = -5i * The imaginary part is -5 and there is no real part. * z = 7 * The real part is 7 and there is no imaginary part.
Let’s consider the following complex numbers, where a, b, c, and d are real scalars:
\[x = a+ib\] \[y = c+id\]
Complex numbers can be easily added and subtracted. Simply add/subtract the real parts and then, separated, add/subtract the imaginary parts. \[x\pm y = (a\pm c) + i(b\pm d)\]
To multiply two complex numbers, you simply have to FOIL the two numbers:
\[xy = (a+ib)(c+id) = ac + iad + ibc + i(i)bd\]
Here we can simplify the result in two ways, first if \(i = \sqrt{-1}\) then \(i(i) = i^2 = -a\). Next, since there are two terms that will have no i and two terms which have an i, we can gather these terms into two groups and then factor out an i.
\[xy = (a+ib)(c+id) = ac + iad + ibc + i(i)bd = (ac-bd) + i(ad+bc)\]
As an example, consider x = 2-3i and y = 4+i. Find: * x+y * \(x+y = 2-3i + 4+i = (2+4) + i(-3+1) = 6-2i\) (Note that y = 4+i can also be written as y = 4+1i (the 1 is implicit)) * x-y * \(x-y = 2-3i - (4+i) = (2-4) + (-3-1)i = -2 -4i\) (The minus sign distributes to the real and imaginary terms of the second complex number) * xy * \(xy = (2-3i)(4+i) = (2)(4) + 2i -3i(4) -3i(i) = 8 + 2i -12i -3(-1) = (8+3) + i(2-12) \newline = 11 - 10i\)
There is an important identity that is commonly used with complex numbers. If an imaginary number is used in the exponent where the base of the exponent is Euler’s number, then the term can also be written as a complex number involving sines and cosines. As a formula: \[e^{i\theta} = cos\theta + isin\theta,\]
where \(\theta\) is any real scalar. This identity is useful because it sometimes it is easier to deal with exponents in an equation and sometimes an equation will simplify easier with trigonometric functions. This identity will become important later when we start manipulating equations with imaginary numbers more often.
Every real or complex number has a complex conjugate which is found by simply negating any imaginary numbers which occur. For example, if z = a+ib, the its complex conjugate, denoted as \(z^*\), is \(z^*\) = a-ib.
As an example, find the complex conjugate of z = 5+2i.
* $z^*$ = 5-2i
The modulus squared of a complex number (denoted as \(|z|^2\) for the complex number z) is just the complex number multiplied by its complex conjugate. If z = a+ib, then \(zz^* = (a+ib)(a-ib) = a^2 -iab + iab -i^2b^2 = a^2b^2\). The modulus (sometimes called the norm) of the complex number is just the square root of the modulus squared: \(|z| = \sqrt{a^2 + b^2}\). Note that both the modulus and the modulus squared are always real numbers.
As an example, find the modulus and modulus squared of z = 4+3i. * Modulus * If z = 4+3i then a = 4 and b = 3 so \(|z| = \sqrt{4^2 + 3^3} = \sqrt{25} = 5\) * Modulus Squared * If z = 4+3i then a = 4 and b = 3 so \(|z|^2 = 4^2+3^2=25\)
At least in Python, complex numbers are built into the programming language. However, instead of denoting the real part of the complex number with i, you use j instead (this is common in some fields like electrical engineering). We can define a complex number in Python using the following code.
We can also easily find the complex conjugate of an number.
Complex Conjugate: (4-3j)
If we have both the complex number and its conjugate then we can compute the modulus and the modulus squared. Note that because we have defined z to be a complex number, calculations using z will result in complex numbers, even if the imaginary component is zero.
# Find the modulus and modulus squared
# Note that the modulus and modulus squared are still
# complex numbers
z_mod_squared = z*z_conj
z_mod = np.sqrt(z_mod_squared)
print("Modulus Squared and Modulus:", z_mod_squared, z_mod)
Modulus Squared and Modulus: (25+0j) (5+0j)
Finally, we can define two complex numbers and perform basic arithmetic on them.
A vector is a one-dimensional structure of numbers. The can either be arranged so that the numbers are side-by-side (called a row vector) or so that the numbers are stacked (called a column vector). For the most part, we will denote a vector with a lowercase letter for the variable and use either a small arrow over the vector, \(\vec{a}\), or a bold letter, a, to denote that the variable represents a vector and not a scalar.
\[ Row\ Vector:\ \vec{a} = \begin{bmatrix} 1 & 2 & 3 \\ \end{bmatrix}\] \[ Column\ Vector:\ \vec{a} = \begin{bmatrix} 1 \\ 2 \\ 3 \\ \end{bmatrix}\]
Each number in the vector is called an element; elements can be real, imaginary, or complex. The number of elements in a vector denotes the length of the vector (also called the rank or the size).
Picture wise, you can think of a vector with a length of two or three as an arrow in space pointing to some location. However, the vectors we deal with in the class many not necessarily correspond to a location or can be longer than 3 elements.
Every vector has a size and a direction. The size of a vector is called its magnitude and is calculated by summing the square of all the elements then taking the square root of the sum. The magnitude of a vector is always a positive, real scalar. As an example, given \(\vec{a} = \begin{bmatrix} 1 & 2 & 3 \\ \end{bmatrix}\), find the magnitude of \(\vec{a}\), denoted as \(|\vec{a}|\) or a.
The direction of a vector is found by dividing the vector by its magnitude. A unit vector, denoted as \(\hat{a}\) is a vector which has a magnitude of 1.
\[\hat{a} = \frac{\vec{a}}{|\vec{a}|}\]
As an example, given \(\vec{a} = \begin{bmatrix} 1 & 2 & 3 \\ \end{bmatrix}\), find the unit vector \(\hat{a}\).
Note that above we have multiplied a vector by a scalar (\(\frac{1}{\sqrt{14}}\)). We will cover this type of calculation in the next section.
Finally, note that the magnitude of the vector multiplied by the unit vector gives the original vector:
\[\vec{a} = |\vec{a}|\hat{a}\]
If you want to add or subtract two vectors, you simply add or subtract the elements in the same positions. Note that the result is a vector and the two vectors you are adding or subtracting must be the same size. As an example, if \(\vec{a} = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix}\) and \(\vec{b} = \begin{bmatrix} 4 & 5 & 6 \end{bmatrix}\), find \(\vec{a}+\vec{b}\) and \(\vec{a}-\vec{b}\).
You can also multiply or divide a vector by a scalar if you multiply or divide every element of the vector by that scalar. Multiplying or dividing a vector by a scalar will result in a vector of the same length as the starting one, just with different values for the elements. As an example, given \(\vec{a} = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix}\) and c = 10, find ca and a/c.
Note that you cannot divide anything by a vector. You also cannot multiply vectors in the traditional sense. In the next two sections we will cover ways to “multiply” two vectors together.
The first way to “multiply” two vectors is called a dot product, but can also be called an inner product or a scalar product. To calculate the dot product between two vectors, just multiply the elements in corresponding positions and then add them all together; the result of a dot product is always a scalar. As an example, if \(\vec{a} = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix}\) and \(\vec{b} = \begin{bmatrix} 4 & 5 & 6 \end{bmatrix}\), find the dot product of \(\vec{a}\) and \(\vec{b}\), \(\vec{a}\cdot\vec{b}\).
A helpful property of dot products is the following identity: \(\vec{a}\cdot\vec{b} = |\vec{a}||\vec{b}|cos\theta\), where \(\theta\) is the angle between the two vectors. This gives us a relatively easy way to find the angle between two vectors, which can be important in many different applications.
The second way to “multiply” vectors is called a cross product. These can be a bit tedious and complicated to calculate by hand, so we will only use these with the help of programming or an online solver like Wolfram Alpha. The result of a cross product is a vector. There is a useful identity for the magnitude of a cross product: \(|\vec{a}\times\vec{b}| = |\vec{a}||\vec{b}|sin\theta\). Cross products are useful because they produce a vector which is perpendicular to both vectors used in the calculation. This will have important applications later in this course as we start to build up the framework we need to perform quantum calculations.
In mathematics courses, vectors will almost always be represented as \(\vec{a}\), a, or sometimes just as a, using only lowercase letters from the front of the alphabet. In quantum mechanics we will use a slightly different notation. First, instead of the English alphabet, we will use Greek letters: \(\alpha\), \(\beta\), \(\phi\), \(\psi\), etc. We will also differentiate between row vectors (which have have mostly been using in this section) and column vectors. We will denote a row vector as \(\langle \psi|\), which is called a bra. We will denote a column vector as \(|\psi\rangle\), which is called a ket.
You can turn a ket into a bra by taking the complex conjugate of each element and then rotating the column vector into a row vector (and vice versa for turning a bra into a ket). For example, if
\[|\psi\rangle = \begin{bmatrix}2-5i \\ 6i \\ 3 \\ \end{bmatrix}\]
then we can write the corresponding bra vector as:
\[\langle \psi | = \begin{bmatrix} 2+5i & -6i & 3 \end{bmatrix}\].
Finally if we write a bra beside a ket (\(\langle\phi | \psi\rangle\) a bra-ket) this is equivalent to taking the dot product between the bra and the get. For an example, find \(\langle\phi | \psi\rangle\) for the following bra and ket vector.
\[\langle \phi | = \begin{bmatrix} 1 & 2 & 3 \\ \end{bmatrix}\]
\[|\psi\rangle = \begin{bmatrix} 2-5i \\ 6i \\ 3 \\ \end{bmatrix}\]
Note that we will typically restrict bras and kets in the class to have a magnitude of 1, so \(\langle\psi | \psi\rangle = 1\) (the square root of the bra-ket of a bra with its corresponding ket is the magnitude).
We define vectors in Python as one-dimensional Numpy arrays. It is important to make sure you are using Numpy arrays and not lists, as some of the functionality shown below will only work with Numpy arrays. First, we can define two vectors and a scalar.
Next, we can add the two vectors, subtract the two vectors, and multiply them by a scalar. You can also divide a vector by a scalar in the same way.
Vector Math: [5 7 9] [-3 -3 -3] [10 20 30]
There are two ways to do a dot product between two vectors. Note that for both the order is important as it determines which is vector is before the dot (note that \(\vec{a}\cdot\vec{b}=\vec{b}\cdot\vec{a}\) but knowing the order the arguments need to be in is very important for other functions like the cross product).
# Dot product two ways
dot1 = np.dot(a,b) #Order is important
dot2 = a.dot(b) # Order is important
print("Dot Product:", dot1, dot2)
Dot Product: 32 32
There is one way to do a cross product in Python and note that the first argument given to the cross function is the vector before the cross sign (\(\vec{a}\times\vec{b}\neq\vec{b}\times\vec{a}\)).
Finally, we can compute the magnitude of a vector, the corresponding unit vector, and ensure that the magnitude of the unit vector is 1.
# Magnitude and unit vector
mag = np.linalg.norm(a)
unit_vector = a/mag
unit_vector_mag = np.linalg.norm(unit_vector)
print("Magnitude, Unit Vector, Magnitude of Unit Vector:", mag, unit_vector, unit_vector_mag)
Magnitude, Unit Vector, Magnitude of Unit Vector: 3.7416573867739413 [0.26726124 0.53452248 0.80178373] 1.0
As a final topics, we will study basic operations on matrices. Matrices are two dimensional data structures with rows and columns. Each entry in a matrix, or the elements, are scalars which can be real or imaginary. If the width and heights of a matrix are the same, then we call it a square matrix. Many of the matrices we will see in this course are square. Note that we will represent a matrix, typically, with an unbolded capital letter. An example of a matrix is:
\[A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{bmatrix}\]
Arithmetic with matrices works much the same was as for vectors. If you want to add or subtract matrices, they must be the same size, and you simply add or subtract the elements in the same locations. You can also multiply or divide a matrix by a scalar by multiplying or dividing every element in the matrix by the scalar. You cannot divide anything by a matrix but you can multiply matrices (next section).
Example: Given the following matrices and c = 10, find A+B, A-B, cA, and A/c.
\[A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{bmatrix}\]
\[B = \begin{bmatrix}9 & 8 & 7 \\ 6 & 5 & 4 \\ 3 & 2 & 1 \\ \end{bmatrix}\]
Two matrices can be multiplied together if the number of columns in the first matrix is the same as the number of rows in the same matrix. Multiplying two matrices together will result in a matrix which has the same number of rows as the first matrix and the same number of columns as the second matrix. Multiplying matrices by hand is not hard, but it is tedious, so we will use Python or a solver like Wolfram Alpha to do the multiplication for us.
Interestingly, in matrix multiplication the order is important, AB and BA are not always the same value (AB \(\neq\) BA). Phrased another way, for most matrices AB - BA \(\neq\) 0. From this we can define the commutator between two matrices as \([A,B] = AB - BA\). If \([A,B]=0\), meaning that the order of multiplication does not matter, then we say that A and B commute.
You can also multiply a vector and a matrix together. It will result in a vector. This is also tedious to do by hand so we will use other tools. Note that you cannot add or subtract a vector and a matrix.
Consider the matrix:
\[A = \begin{bmatrix}1 & 2i & 3 \\ 4+i & 5 & 6 \\ 7 & 8 & 9-3i \\ \end{bmatrix}\]
The transpose of A, denoted as \(A^T\) is a matrix that is found by switching the rows and columns of A. Basically, the first row of A becomes the first column of \(A^T\), the second row becomes the second column, and the third row becomes the third column. Then,
\[A^T = \begin{bmatrix} 1 & 4+i & 7 \\ 2i & 5 & 8 \\ 3 & 6 & 9-3i \\ \end{bmatrix}\]
The complex conjugate of a matrix, denoted as \(A^*\) is found by simply taking the complex conjugate of every element of A. Then,
\[A^* = \begin{bmatrix}1 & -2i & 3 \\ 4-i & 5 & 6 \\ 7 & 8 & 9+3i \\ \end{bmatrix}\]
Next, the adjoint of a matrix, represented as \((A^T)^*\) or \(A^\dagger\) is found by taking both the transpose and the complex conjugate of a matrix. The order you do these operations in does not matter. So, for our matrix, its adjoint is:
\[A^\dagger = \begin{bmatrix} 1 & 4-i & 7 \\ -2i & 5 & 8 \\ 3 & 6 & 9+3i \\ \end{bmatrix}\]
Finally, if \(A = A^\dagger\) then the matrix is said to be Hermitian. Many of the matrices we will use in this class will be Hermitian (the reason why will be discussed later). Our matrix in this example is not Hermitian since \(A\neq A^\dagger\). There are other properties of matrices that we will use throughout the course, but these three will get us started as we build up the frame work we need over the next couple of weeks.
A matrix is not represented in Dirac notation any differently than normal, but sometimes you will see the matrices written with a “hat” symbol, \(\hat{A}\). The term \(A|\psi\rangle\) shows a matrix, A, being multiplied by the ket vector \(\psi\). The result of this operation is a ket vector. The term \(\langle \phi | A | \psi \rangle\) is a bra vector multiplied by a matrix then the result is multiplied by a let vector. The result of this term is a scalar.
The final topic we will cover are eigenvalues and eigenvectors. Eigenvalues, which are scalars, and eigenvectors are special values and vectors that each matrix has. The eigenvalues, \(\lambda\), and the eigenvectors, x, are the values that solve this equation for some matrix A: Ax = \(\lambda\)x. For a NxN matrix, there are N eigenvalues and N corresponding eigenvectors, though they do not all have to be unique (if the same eigenvalue occurs more than once it is said to be degenerate).
If we rewrite the above equation, then we get Ax-\(\lambda\)x = 0, so you can think of the eigenvalues as the roots of a matrix. Finding eigenvalues by hand is possible but is a complicated and error prone process, so we will use Python or other matrix solvers.
Matrices in Python are represented as two-dimensional Numpy arrays (again, make sure you are using Numpy arrays and not lists). We can define two matrices, a vector, and a scalar as follows.
We can start by adding and subtracting the two matrices.
# Matrix addition and subtraction
add = A+B
sub = A-B
print("Matrix Addition:", add)
print("Matrix Subtraction:", sub)
print()
Matrix Addition: [[10 10 10]
[10 10 10]
[10 10 10]]
Matrix Subtraction: [[-8 -6 -4]
[-2 0 2]
[ 4 6 8]]
Next, let’s do some matrix multiplication and calculate the commutator. Note that if you want to multiply two matrices, use the @ symbol instead of the * symbol. Using the * symbol results in element-wise multiplication instead of actual matrix multiplication.
# Matrix-matrix multiplication
# Do not use the * symbol!!
mul1 = A@B
mul2 = B@A
commutator = mul1 - mul2
print("Matrix Multiplication 1:",mul1)
print("Matrix Multiplication 2:", mul2)
print("Commutator:", commutator)
print()
Matrix Multiplication 1: [[ 30 24 18]
[ 84 69 54]
[138 114 90]]
Matrix Multiplication 2: [[ 90 114 138]
[ 54 69 84]
[ 18 24 30]]
Commutator: [[ -60 -90 -120]
[ 30 0 -30]
[ 120 90 60]]
Next, we can also use the @ symbol to multiply vectors and matrices.
Matrix-Vector Multiplication: [ 28 64 100]
However, if you want to multiply a matrix by a scalar then you use the * symbol for the multiplication.
# Matrix-Scalar Multiplication
# Do not use the * symbol!!
mul4 = c*B
print("Matrix-Scalar Multiplixation:", mul4)
print()
Matrix-Scalar Multiplixation: [[90 80 70]
[60 50 40]
[30 20 10]]
Now, we can calculate the transpose of a matrix by using .T after the name of the matrix. The complex conjugate of the matrix can be found using the same Numpy function we used in the complex numbers section and the adjoint can be found by combining these.
# Transpose and Adjoint
transpose = A.T
adjoint = np.conj(B).T
print("Transpose:", transpose)
print("Adjoint:", adjoint)
print()
Transpose: [[1 4 7]
[2 5 8]
[3 6 9]]
Adjoint: [[9 6 3]
[8 5 2]
[7 4 1]]
Finally, we can find the eigenvalues and eigenvectors of a matrix using the Numpy library. Note that the returned variable eigenvalues
is a one-dimensional array where each element is a different eigenvalue of the matrix. The returned variable eigenvectors
is a two-dimensional matrix where each column is an eigenvalue of the matrix. Note that the first element in eigenvalues
corresponds to the first column of eigenvectors
, the second element to the second column, and so on.
# Eigenvalues and Eigenvectors
# Note that the eigenvectors of A are the columns of the matrix
# eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(A)
print("Eigenvalues:",eigenvalues)
print("Eigenvectors:",eigenvectors)
Eigenvalues: [ 1.61168440e+01 -1.11684397e+00 -8.58274334e-16]
Eigenvectors: [[-0.23197069 -0.78583024 0.40824829]
[-0.52532209 -0.08675134 -0.81649658]
[-0.8186735 0.61232756 0.40824829]]