CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
weijie-chen

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: weijie-chen/Linear-Algebra-With-Python
Path: blob/master/notebooks/Chapter 8 - Vector Space and Subspace.ipynb
Views: 449
Kernel: Python 3
import matplotlib.pyplot as plt import numpy as np import sympy as sy sy.init_printing()

Vector Space

A vector space, as its name indicates, is the space for vectors, which defines two operations, addition and multiplication by scalars, subject to 1010 axioms below.

  1. The sum of u{u} and v{v}, denoted by u+v,{u}+{v}, is in VV

  2. u+v=v+u{u}+{v}={v}+{u}

  3. (u+v)+w=u+(v+w)({u}+{v})+{w}={u}+({v}+{w})

  4. There is a zero vector 00 in VV such that u+0=u{u}+{0}={u}

  5. For each u{u} in VV, there is a vector u-{u} in VV such that u+(u)=0{u}+(-{u})={0}

  6. The scalar multiple of u{u} by c,c, denoted by cu,c {u}, is in VV

  7. c(u+v)=cu+cvc({u}+{v})=c {u}+c {v}

  8. (c+d)u=cu+du(c+d) {u}=c {u}+d {u}

  9. c(du)=(cd)uc(d {u})=(c d) {u}

  10. 1u=u1 {u}={u}

Though 1010 axioms seem quite apparent and superfluous, simply remember this: addition and multiplication are closed in vector space.

All axioms are self-explanatory without proof, we can visualize axiom 77 with visualization.

def vec_space_ax_7(u, v, c): '''vecSpaceAx7(u, v, c), to demonstrate Axiom 7.''' fig, ax = plt.subplots(figsize=(7, 7)) # Plot vectors u, v, u+v ax.arrow(0, 0, u[0], u[1], color='red', width=0.08, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) ax.arrow(0, 0, v[0], v[1], color='blue', width=0.08, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) ax.arrow(0, 0, u[0]+v[0], u[1]+v[1], color='green', width=0.08, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) # Plot scaled vectors c*u, c*v, c*(u+v) ax.arrow(0, 0, c*u[0], c*u[1], color='red', width=0.08, alpha=0.5, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) ax.arrow(0, 0, c*v[0], c*v[1], color='blue', width=0.08, alpha=0.5, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) ax.arrow(0, 0, c*(u[0]+v[0]), c*(u[1]+v[1]), color='green', width=0.08, alpha=0.5, length_includes_head=True, head_width=0.3, head_length=0.6, overhang=0.4) # Plot dashed lines lines = [ ([u[0], u[1]], [u[0] + v[0], u[1] + v[1]], 'red'), ([v[0], v[1]], [u[0] + v[0], u[1] + v[1]], 'blue'), ([c*v[0], c*v[1]], [c*(u[0] + v[0]), c*(u[1] + v[1])], 'blue'), ([c*u[0], c*u[1]], [c*(u[0] + v[0]), c*(u[1] + v[1])], 'blue') ] for (p1, p2, color) in lines: ax.plot([p1[0], p2[0]], [p1[1], p2[1]], ls='--', lw=3, color=color, alpha=0.5) # Annotate points points = [ (u[0], u[1]), (v[0], v[1]), (u[0]+v[0], u[1]+v[1]), (c*u[0], c*u[1]), (c*v[0], c*v[1]), (c*(u[0]+v[0]), c*(u[1]+v[1])) ] for (x, y) in points: ax.text(x, y, f'$(%.0d, %.0d)$' % (x, y), size=16) # Set title and axis properties ax.set_title(r'Axiom 7: $c(\mathbf{u}+\mathbf{v})=c \mathbf{u}+c \mathbf{v}$', size=19, color='red') ax.axis([0, np.max(c*u)+6, 0, np.max(c*v)+6]) ax.grid(True) if __name__ == '__main__': u = np.array([2, 3]) v = np.array([3, 1]) c = 2 vec_space_ax_7(u, v, c)
Image in a Jupyter notebook

Try different vectors.

u = np.array([1, 3]) v = np.array([5, 2]) vec_space_ax_7(u, v, 2)
Image in a Jupyter notebook

However the vector space has more general meaning than containing vectors, the functions and polynomials can also be in the vector space as we have show in the section of linear dependence.

The difference is that the functions has infinite number of elements (continuous functions) in contrast to vectors.

We can demonstrate in the vector space for functions by plotting two trigonometric functions: sin(x)\sin(x) and cos(x+1)\cos{(x+1)} (stem plot), their addition in vector space is the pink shaded plot.

def sin_cos_vis(x1, x2, c): '''Syntax funcVecSp(x), x is the domain, for instance, x = np.linspace(-3, 3, 20)''' fig, ax = plt.subplots(figsize=(10, 10)) y1 = c * np.sin(x1) ax.stem(x1, y1, linefmt='red', markerfmt='ro', basefmt='r-', label=r'$\sin(x)$') y2 = c * np.cos(x2 + 1) ax.stem(x2, y2, linefmt='blue', markerfmt='bo', basefmt='b-', label=r'$\cos(x)$') y3 = c * (np.sin(x1) + np.cos(x2 + 1)) ax.plot(x2, y3, lw=4, color='red', alpha=0.6) ax.fill_between(x2, y3, 0, color='red', alpha=0.3) str1 = r'$\sin(x) + \cos(x+1)$' ax.annotate(str1, xy=(1, 2 * (np.sin(1) + np.cos(1 + 1))), xytext=(0, 3), weight='bold', color='r', fontsize=18, arrowprops=dict(arrowstyle='->', connectionstyle='arc3', color='b')) ax.axis([-5, 5, -4, 4]) ax.legend() if __name__ == '__main__': x1 = np.arange(-5, 5, 0.3) x2 = np.arange(-5.1, 4.9, 0.3) c = 2 sin_cos_vis(x1, x2, c)
Image in a Jupyter notebook

So we can say that sin(x)+cos(x+1)\sin{(x)}+\cos{(x+1)} is in the same vector space of sin(x)\sin{(x)} and cos(x+1)\cos{(x+1)}.

Subspace

A subspace is one of the most important concept in linear algebra.

A subspace resides in a vector space VV, we can denoted it as HH. Only two properties needs to be demonstrated:

  1. HH has zero vector.

  2. Closed under vector addition and scalar multiplication.

To help you understand subspace:

  1. Any line passes through (0,0)(0, 0) in R2\mathbb{R}^2 is a subspace of R2\mathbb{R}^2.

  2. Any plane passes through (0,0,0)(0, 0, 0) in R3\mathbb{R}^3 is a subspace of R3\mathbb{R}^3.

Next we will visualize the subspace.

Visualization of Subspace of R2\mathbb{R}^2

fig, ax = plt.subplots(figsize = (10, 10)) ####################### Arrows ####################### x = np.arange(-10, 11, 1) y = 4/6*x ax.plot(x, y, lw = 4, color = 'blue',label = r'$y = \frac{2}{3}x$, subspace of $\mathbf{R}^2$') y = -3+4/6*x ax.plot(x, y, lw = 4, color = 'red',label = r'$y = -3+\frac{2}{3}x$, not a subspace of $\mathbf{R}^2$') ax.grid(True) ax.set_title('Visualization of Subspace in $R^2$ ', size = 18) ax.scatter(0, 0, s= 100, fc = 'black', ec = 'red') ax.text(-2, 0, '$(0,0)$',size = 18) ax.legend(fontsize = 16) ax.axis([-10, 10, -10, 10]) ax.set_xlabel('x-axis', size = 18) ax.set_ylabel('y-axis', size = 18) plt.show()
Image in a Jupyter notebook

Visualization of Subspace of R3\mathbb{R}^3

Consider a span of two vectors u=(1,2,1)Tu = (1,-2,1)^T and v=(2,1,2)Tv=(2,1,2)^T. The span of (u,v)(u,v) is a subspace of R3\mathbb{R}^3, where ss and tt are the scalars of the vectors.

[xyz]=s[121]+t[212]=[s+2t2s+ts+2t]\left[ \begin{matrix} x\\ y\\ z \end{matrix} \right]= s\left[ \begin{matrix} 1\\ -2\\ 1 \end{matrix} \right]+ t\left[ \begin{matrix} 2\\ 1\\ 2 \end{matrix} \right]= \left[ \begin{matrix} s+2t\\ -2s+t\\ s+2t \end{matrix} \right]

We also plot a plan which is not a subspace by adding 22 onto the third equation, i.e. z=s+2t+2z= s+2t+2.

Remember matplotlib does not have 3D engine, we have to pan to a proper angle to show the layout.

#%matplotlib notebook, use this only if you are in Jupyter Notebook fig = plt.figure(figsize = (8,8)) ax = fig.add_subplot(111,projection='3d') s = np.linspace(-1, 1, 10) t = np.linspace(-1, 1, 10) S, T = np.meshgrid(s, t) X = S+2*T Y = -2*S+T Z = S+2*T ax.plot_surface(X, Y, Z, alpha = .9,cmap=plt.cm.coolwarm) Z2 = S+2*T+2 # this is not a subspace anymore ax.plot_surface(X, Y, Z2, alpha = .6 ,cmap=plt.cm.jet) ax.scatter(0,0,0, s = 200, color = 'red') ax.text(0,0,0,'$(0,0,0)$',size = 18, zorder = 5) ax.set_title('Visualization of Subspace of $\mathbb{R}^3$', x = .5, y = 1.1, size = 20) ax.set_xlabel('x-axis', size = 18) ax.set_ylabel('y-axis', size = 18) ax.set_zlabel('z-axis', size = 18) ax.view_init(elev=-29, azim=132) plt.show()
Image in a Jupyter notebook

As you can see the plane contains (0,0,0)(0,0,0) is a subspace, but the other plane is not.

Span

We have mentioned span quite a few times before; now we provide a formal definition of a span. Use span(S)\text{span}(S) to denote the span of a subset {v1,v2,,vn}\{v_1, v_2, \ldots, v_n\}, which is a linear combination in vector space VV.

span(S)={c1v1+c2v2++cnvn:c1,,cnR}\text{span}(S) = \{c_1v_1 + c_2v_2 + \cdots + c_nv_n : c_1, \ldots, c_n \in \mathbb{R}\}

The span of two vectors in R3\mathbb{R}^3 is a plane which is also a subspace of R3\mathbb{R}^3, and any two vectors span a plane. For example, given two vectors (3,9,2)(3, 9, 2) and (1,7,5)(1, 7, 5), any linear combination is a span, i.e., s(3,9,2)T+t(1,7,5)Ts(3, 9, 2)^T + t(1, 7, 5)^T.

For a more general span, a basic fact of matrix multiplication can assist us in demonstrating:

AB=A[b1 b2 b3,,bp]=[Ab1 Ab2 Ab3,,Abp]AB = A[b_1\ b_2\ b_3, \ldots, b_p] = [Ab_1\ Ab_2\ Ab_3, \ldots, Ab_p]

where AA is the spanning set of vectors, and bkb_k is a vector of weights for the linear combination. We can generate a random matrix BB to form various linear combinations to visually verify if they are all contained in the spanned plane.

We define:

A=[319725]biN(0,1)A = \left[\begin{array}{rr} 3 & 1 \\ 9 & 7 \\ 2 & 5 \end{array}\right] \qquad b_i \sim N(\mathbf{0}, 1)
A = np.array([[3,9,2],[1,7,5]]).T B = 10*np.random.randn(2, 300) # i = 300, i.e. 300 random weight vectors vecs = A@B s = np.linspace(-10, 10, 10) t = np.linspace(-10, 10, 10) S, T = np.meshgrid(s, t) X = 3*S+T Y = 9*S+7*T Z = 2*S+5*T fig, ax = plt.subplots(figsize = (10, 10)) ax = fig.add_subplot(projection='3d') ax.plot_wireframe(X, Y, Z, linewidth = 1.5, color = 'k', alpha = .6) ax.scatter(0,0,0, s =200, ec = 'red', fc = 'black') colors = np.random.rand(vecs.shape[1],3) for i in range(vecs.shape[1]): vec = np.array([[0, 0, 0, vecs[0,i], vecs[1,i], vecs[2,i]]]) X, Y, Z, U, V, W = zip(*vec) ax.quiver(X, Y, Z, U, V, W, length=1,color = colors[i], normalize=False, arrow_length_ratio = .07, pivot = 'tail', linestyles = 'solid',linewidths = 2, alpha = .9) ax.view_init(elev=-156, azim=-56) plt.show()
Image in a Jupyter notebook

Pan around the plot, we confirm that all the vectors are in the Span(u,v)\text{Span}(u,v).

Span of R3\mathbb{R}^3

Reproduce the code above, but we have three vectors: (1,0,1)(1,0,1), (1,1,0)(1,1,0), (0,1,1)(0,1,1). Again we create a random coefficent matrix to form different linear combinations.

A = np.array([[1,0,1],[1,1,0],[0,1,1]]).T B = 5*np.random.randn(3, 300) vecs = A@B s = np.linspace(-10, 10, 10) t = np.linspace(-10, 10, 10) S, T = np.meshgrid(s, t) X = S+T Y = T Z = S fig, ax = plt.subplots(figsize = (10, 10)) ax = fig.add_subplot(projection='3d') ax.plot_wireframe(X, Y, Z, linewidth = 1.5, color = 'k', alpha = .6) ax.scatter(0,0,0, s =200, ec = 'red', fc = 'black') colors = np.random.rand(vecs.shape[1],3) for i in range(vecs.shape[1]): vec = np.array([[0, 0, 0, vecs[0,i], vecs[1,i], vecs[2,i]]]) X, Y, Z, U, V, W = zip(*vec) ax.quiver(X, Y, Z, U, V, W, length=1,color = colors[i], normalize=False, arrow_length_ratio = .07, pivot = 'tail', linestyles = 'solid',linewidths = 2, alpha = .9) ax.view_init(elev=21, azim=-110) plt.show()
Image in a Jupyter notebook

The vectors are pointing every possible directions in R3\mathbb{R}^3, and all of them bounded in the span of those three vectors.