Disabled external gits
This commit is contained in:
382
cs457-gc/assignment_2_1/notebook/hw_2.1.ipynb
Normal file
382
cs457-gc/assignment_2_1/notebook/hw_2.1.ipynb
Normal file
@@ -0,0 +1,382 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Description\n",
|
||||
"\n",
|
||||
"This notebook intends to gather all the functionalities you'll have to implement for assignment 2.1. You will have to generate an elastic solid, deform it, compute the associated Jacobian of the deformation map $\\phi$, and implement pinning constraints. You will also visualize the eigenvectors and eigenvalues of the metric tensor, given a prescribed deformation.\n",
|
||||
"\n",
|
||||
"# Load libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import igl\n",
|
||||
"import meshplot as mp\n",
|
||||
"\n",
|
||||
"import sys as _sys\n",
|
||||
"_sys.path.append(\"../src\")\n",
|
||||
"from elasticsolid import *\n",
|
||||
"from eigendecomposition_metric import *\n",
|
||||
"\n",
|
||||
"shadingOptions = {\n",
|
||||
" \"flat\":True,\n",
|
||||
" \"wireframe\":False, \n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"rot = np.array(\n",
|
||||
" [[1, 0, 0 ],\n",
|
||||
" [0, 0, 1],\n",
|
||||
" [0, -1, 0 ]]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Load mesh\n",
|
||||
"\n",
|
||||
"Several meshes are available for you to play with under `data/`: `ball.obj`, `dinosaur.obj`, and `beam.obj`. You can also uncomment the few commented lines below to manipulate a simple mesh made out of 2 tetrahedra."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "33e8252ccc4d4c9298094b0dc3675ee4",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"v, _, _, t, _, _ = igl.read_obj(\"../data/dinosaur.obj\")\n",
|
||||
"\n",
|
||||
"# t = np.array([\n",
|
||||
"# [0, 1, 2, 3],\n",
|
||||
"# [1, 2, 3, 4]\n",
|
||||
"# ])\n",
|
||||
"# v = np.array([\n",
|
||||
"# [0., 0., 0.],\n",
|
||||
"# [1., 0., 0.],\n",
|
||||
"# [0., 1., 0.],\n",
|
||||
"# [0., 0., 1.],\n",
|
||||
"# [2/3, 2/3, 2/3]\n",
|
||||
"# ])\n",
|
||||
"\n",
|
||||
"aabb = np.max(v, axis=0) - np.min(v, axis=0)\n",
|
||||
"length_scale = np.mean(aabb)\n",
|
||||
"\n",
|
||||
"p = mp.plot(v @ rot.T, t, shading=shadingOptions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Manipulate elastic solids\n",
|
||||
"\n",
|
||||
"## Instanciation\n",
|
||||
"\n",
|
||||
"The rest shape matrices $D_m$ and their inverse matrices $B_m$ are computed during instanciation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rho = 131 # [kg.m-3]\n",
|
||||
"solid = ElasticSolid(v, t, rho=rho)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Deform the mesh\n",
|
||||
"\n",
|
||||
"This part involves Jacobian computation which relies on deformed shape matrices $D_s$."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"scrolled": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "02c94de8642645d8aab800877f8ddbce",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<meshplot.Viewer.Viewer at 0x7fa7dc789070>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"v_def = v.copy()\n",
|
||||
"v_def[:, 2] *= 2.\n",
|
||||
"solid.update_def_shape(v_def)\n",
|
||||
"\n",
|
||||
"mp.plot(solid.v_def @ rot.T, solid.t, shading=shadingOptions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Visualize some properties of the metric tensor\n",
|
||||
"\n",
|
||||
"The metric tensor measures how stretched and sheared directions in the undeformed space are under the deformation $\\phi$. It is defined from the Jacobian of the deformation $\\mathbf{F}$ as follow (see the handout for a derivation):\n",
|
||||
"\n",
|
||||
"$$\\mathbf{M} = \\mathbf{F}^T \\mathbf{F}$$\n",
|
||||
"\n",
|
||||
"We intend to plot the eigenvectors coloured by the corresponding eigenvalues in the next cell."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "6ff42798692c4a29ad4a37f40ca77a84",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# We limit ourselves to stretching the mesh in the z direction\n",
|
||||
"# Feel free to experiment with other kinds of deformations!\n",
|
||||
"\n",
|
||||
"v_def = v.copy()\n",
|
||||
"v_def[:, 2] *= 2.0\n",
|
||||
"solid.update_def_shape(v_def)\n",
|
||||
"\n",
|
||||
"squared_eigvals, eigvecs = compute_eigendecomposition_metric(solid.F)\n",
|
||||
"plot_eigendecomposition_metric(solid, squared_eigvals, eigvecs, rot, scale=0.05)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Pin vertices of the mesh\n",
|
||||
"\n",
|
||||
"Pass a `pin_idx` to the constructor, compute the mask for deformations."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"maxZ = np.max(solid.v_rest[:, 2])\n",
|
||||
"pin_idx = np.arange(solid.v_rest.shape[0])[solid.v_rest[:, 2] > maxZ - 0.1 * aabb[2]]\n",
|
||||
"\n",
|
||||
"v_def = v.copy()\n",
|
||||
"v_def[:, 2] -= 0.1 * aabb[2]\n",
|
||||
"solid.update_def_shape(v_def)\n",
|
||||
"\n",
|
||||
"solid_pinned = ElasticSolid(v, t, rho=rho, pin_idx=pin_idx)\n",
|
||||
"solid_pinned.update_def_shape(v_def)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "13f958a33ec945ca979aca15d7381e01",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"p = mp.plot(solid_pinned.v_def @ rot.T, t, shading=shadingOptions)\n",
|
||||
"p.add_points(solid_pinned.v_def[pin_idx, :] @ rot.T, shading={\"point_color\":\"black\", \"point_size\": 0.1 * length_scale})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 1.2.4 Derivation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Volume of tetrahedron ($X_1, X_2, X_3, X_4$) is given by $\\frac{1}{6}|det(D_m)|$\n",
|
||||
"\n",
|
||||
"We can decompose the provided formula:\n",
|
||||
"\n",
|
||||
"$Vol = \\frac{1}{6}|det(D_m)| = \\frac{1}{6}|D_{m1}^T \\cdot (D_{m2} \\times D_{m3})|$\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Next, we build 3 vectors:\n",
|
||||
"\n",
|
||||
"$V_0 = X_1 - X_4 = \\begin{pmatrix}X_{x1}-X_{x4} \\\\ Y_{x1}-Y_{x4} \\\\ Z_{x1}- Z_{x4} \\end{pmatrix}$\n",
|
||||
"\n",
|
||||
"$V_1 = X_2 - X_4 = \\begin{pmatrix}X_{x2}-X_{x4} \\\\ Y_{x2}-Y_{x4} \\\\ Z_{x2}- Z_{x4} \\end{pmatrix}$\n",
|
||||
"\n",
|
||||
"$V_2 = X_3 - X_4 = \\begin{pmatrix}X_{x3}-X_{x4} \\\\ Y_{x3}-Y_{x4} \\\\ Z_{x3}- Z_{x4} \\end{pmatrix}$\n",
|
||||
"\n",
|
||||
"We then compute the base as:\n",
|
||||
"\n",
|
||||
"$B = V_1 \\times V_2$\n",
|
||||
"\n",
|
||||
"And also the height as:\n",
|
||||
"\n",
|
||||
"$H = V_0$\n",
|
||||
"\n",
|
||||
"From this we can compute the volume:\n",
|
||||
"\n",
|
||||
"$Vol = \\frac{1}{6} \\cdot B \\cdot H = \\frac{1}{6} V_0 \\cdot (V_1 \\times V_2)$\n",
|
||||
"\n",
|
||||
"We can note the similarity between both fomulas. We can note the equality between both formulas: \n",
|
||||
"\n",
|
||||
"$V_0 = D_{m1}, V_1 = D_{m2}, V_2 = D_{m3}$\n",
|
||||
"\n",
|
||||
"Note that the absolute value is not directly taken into account since its absolute volume and not signed volume.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 1.2.7 Derivation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Show that: $Vol(x_1, x_2, x_3, x_4)/Vol(X_1, X_2, X_3, X_4) = |det(F)|$\n",
|
||||
"\n",
|
||||
"Since we know that $F = D_s D_m^{-1}$, and that: $V = \\frac{1}{6}|det(D_m)|$\n",
|
||||
"\n",
|
||||
"We can drag the det and abs into it:\n",
|
||||
"\n",
|
||||
"$|det(F)| = \\frac{|det(D_s)|}{|det(D_m)|} = \\frac{\\frac{1}{6}|det(D_s)|}{\\frac{1}{6}|det(D_m)|} = \\frac{Vol(x_1, x_2, x_3, x_4)}{Vol(X_1, X_2, X_3, X_4)}$\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.7"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@@ -0,0 +1,268 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import time"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Tutorial: Higher Order Array Manipulation\n",
|
||||
"\n",
|
||||
"For the sake of simplicity, we define $n$-th order tensors as arrays of dimension $n$. A $0$-th order array is a scalar, a $1$-st order array is a vector in $\\mathbb{R}^{d_1}$, and a $2$-nd order array is a matrix in $\\mathbb{R}^{d_1\\times d_2}$. Going further, a $n$-th order array is an element of $\\mathbb{R}^{d_1\\times...\\times d_n}$ for some dimensions $(d_i)_{i\\in[n]}$.\n",
|
||||
"\n",
|
||||
"## Declaration"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Declare a third order array \n",
|
||||
"d1, d2, d3 = 2, 3, 5\n",
|
||||
"A = np.random.rand(d1, d2, d3)\n",
|
||||
"\n",
|
||||
"print(\"The shape of A is {}\".format(A.shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Indexing\n",
|
||||
"\n",
|
||||
"Say we have a $3$-rd order array $\\mathbf{A}\\in\\mathbb{R}^{d_1\\times d_2\\times d_3}$. Indexing and slicing works as for lower order arrays:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(\"A[0] has shape {}\".format(A[0].shape))\n",
|
||||
"print(\"A[:, 1:, :] has shape {}\".format(A[:, 1:, :].shape))\n",
|
||||
"print(\"A[:, 1, 2:4] has shape {}\".format(A[:, 1, 2:4].shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can also use a different indexing array $\\mathbf{b}$ to index $\\mathbf{A}$. This indexing operates on the first dimension of $\\mathbf{A}$, meaning that if $\\mathbf{b}\\in\\mathbb{R}^{l_1\\times l_2}$, then `A[b]` will have shape $l_1\\times l_2\\times d_2\\times d_3$."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"b = np.array([0, 0, 1, 0])\n",
|
||||
"print(\"If A has shape {}, b has shape {}, then A[b] has shape {}.\".format(A.shape, b.shape, A[b].shape))\n",
|
||||
"\n",
|
||||
"b = np.array([[0, 0, 1, 0], [1, 1, 0, 1]])\n",
|
||||
"print(\"If A has shape {}, b has shape {}, then A[b] has shape {}.\".format(A.shape, b.shape, A[b].shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"... This works provided the indexing array $\\mathbf{b}$ has integer values comprised between $0$ and $d_{1}-1$ (included)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"try:\n",
|
||||
" b = np.array([0, 0, 2, 0])\n",
|
||||
" A[b]\n",
|
||||
"except Exception as e:\n",
|
||||
" print(\"We have an out-of bound indexing: d_1=1 but max b=2\")\n",
|
||||
" print(\"The exception is: {}\".format(e))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Operations\n",
|
||||
"\n",
|
||||
"Imagine now that we have a batch of $1000$ $d\\times d$ matrices: $(\\mathbf{a}_i)_{i\\in[1000]}$, for which we want to compute the trace. We could loop over the matrices and compute the traces separately."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"d = 2\n",
|
||||
"\n",
|
||||
"ais = [np.random.rand(d, d) for i in range(1000)]\n",
|
||||
"\n",
|
||||
"start = time.time()\n",
|
||||
"traces = ...\n",
|
||||
"end = time.time()\n",
|
||||
"\n",
|
||||
"print(\"Elapsed time: {:.2e}s.\".format(end - start))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Alternatively, we could vectorize this operation using a three dimensional array $\\mathbf{A}\\in\\mathbb{R}^{3\\times d\\times d}$ that contains the stacked matrices."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"A = np.stack(ais, axis=0)\n",
|
||||
"\n",
|
||||
"print(\"A has shape {}\".format(A.shape))\n",
|
||||
"\n",
|
||||
"start = time.time()\n",
|
||||
"traces = ...\n",
|
||||
"end = time.time()\n",
|
||||
"\n",
|
||||
"print(\"Elapsed time: {:.2e}s.\".format(end - start))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"And we reduced the computation time by an order of magnitude! A different option that we will use extensively during part 3 is to use [Einstein summation](https://en.wikipedia.org/wiki/Einstein_notation). For the traces computation this would be written: $\\mathbf{A}_{i,j,j}$. This can be done with Numpy with the method [`np.einsum`](https://numpy.org/doc/stable/reference/generated/numpy.einsum.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"start = time.time()\n",
|
||||
"traces = ...\n",
|
||||
"end = time.time()\n",
|
||||
"\n",
|
||||
"print(\"Elapsed time: {:.2e}s.\".format(end - start))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"As efficient as the trace method! Also, `np.einsum` is highly flexible. It can compute the transpose of a batch of arrays, or various kinds of matrix multiplications."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ais = [np.random.rand(2, 3) for i in range(1000)]\n",
|
||||
"\n",
|
||||
"# Transpose each stacked matrices\n",
|
||||
"A = np.stack(ais, axis=0)\n",
|
||||
"print(\"A has shape {}\".format(A.shape))\n",
|
||||
"AT = ...\n",
|
||||
"print(\"A^T has shape {}\".format(AT.shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Below we show how to compute $\\mathbf{a}_i^T\\mathbf{a}_i$ for some matrices $\\mathbf{a}_i\\in\\mathbb{R}^{2\\times 3}$ using `np.einsum`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(\"A has shape {}\".format(A.shape))\n",
|
||||
"product_As = ...\n",
|
||||
"print(\"Stacked ai^T.ai has shape {}\".format(product_As.shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To scale each $\\mathbf{a}_i$ by a weight $w_i$, we can still use `np.einsum`. Define the vector containing all the weights $\\mathbf{w}=(w_i)_i$, we have:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"w = np.random.rand(A.shape[0])\n",
|
||||
"weighted_A = ...\n",
|
||||
"print(\"Weighted and stacked ai has shape {}\".format(weighted_A.shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.10"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
"nav_menu": {},
|
||||
"number_sections": true,
|
||||
"sideBar": true,
|
||||
"skip_h1_title": false,
|
||||
"title_cell": "Table of Contents",
|
||||
"title_sidebar": "Contents",
|
||||
"toc_cell": false,
|
||||
"toc_position": {},
|
||||
"toc_section_display": true,
|
||||
"toc_window_display": false
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
Reference in New Issue
Block a user