|
2 | 2 | "cells": [
|
3 | 3 | {
|
4 | 4 | "cell_type": "code",
|
5 |
| - "execution_count": 3, |
| 5 | + "execution_count": 1, |
6 | 6 | "metadata": {},
|
7 | 7 | "outputs": [],
|
8 | 8 | "source": [
|
|
29 | 29 | },
|
30 | 30 | {
|
31 | 31 | "cell_type": "code",
|
32 |
| - "execution_count": 10, |
| 32 | + "execution_count": 2, |
33 | 33 | "metadata": {},
|
34 | 34 | "outputs": [
|
35 | 35 | {
|
|
54 | 54 | },
|
55 | 55 | {
|
56 | 56 | "cell_type": "code",
|
57 |
| - "execution_count": 11, |
| 57 | + "execution_count": 3, |
58 | 58 | "metadata": {},
|
59 | 59 | "outputs": [
|
60 | 60 | {
|
|
79 | 79 | },
|
80 | 80 | {
|
81 | 81 | "cell_type": "code",
|
82 |
| - "execution_count": 12, |
| 82 | + "execution_count": 4, |
83 | 83 | "metadata": {},
|
84 | 84 | "outputs": [
|
85 | 85 | {
|
|
108 | 108 | "cell_type": "markdown",
|
109 | 109 | "metadata": {},
|
110 | 110 | "source": [
|
111 |
| - "### 最短路径" |
| 111 | + "### 矩阵向量相乘" |
112 | 112 | ]
|
113 | 113 | },
|
114 | 114 | {
|
115 | 115 | "cell_type": "code",
|
116 |
| - "execution_count": 14, |
117 |
| - "metadata": {}, |
118 |
| - "outputs": [ |
119 |
| - { |
120 |
| - "ename": "SyntaxError", |
121 |
| - "evalue": "invalid syntax (<ipython-input-14-adc4f84eb492>, line 3)", |
122 |
| - "output_type": "error", |
123 |
| - "traceback": [ |
124 |
| - "\u001b[1;36m File \u001b[1;32m\"<ipython-input-14-adc4f84eb492>\"\u001b[1;36m, line \u001b[1;32m3\u001b[0m\n\u001b[1;33m digraph graph1 {\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" |
125 |
| - ] |
126 |
| - } |
127 |
| - ], |
128 |
| - "source": [ |
129 |
| - "\n", |
130 |
| - "#%figonly=使用稀疏矩阵可以表示有向图\n", |
131 |
| - "digraph graph1 {\n", |
132 |
| - " rankdir=LR;\n", |
133 |
| - " size=\"8,5\"\n", |
134 |
| - " node [shape = circle];\n", |
135 |
| - " A -> B [ label = \"10\" ];\n", |
136 |
| - " B -> C [ label = \"5\" ];\n", |
137 |
| - " A -> C [ label = \"3\" ];\n", |
138 |
| - " C -> D [ label = \"7\" ];\n", |
139 |
| - " D -> A [ label = \"4\" ];\n", |
140 |
| - " D -> C [ label = \"6\" ];\n", |
141 |
| - "}" |
142 |
| - ] |
143 |
| - }, |
144 |
| - { |
145 |
| - "cell_type": "code", |
146 |
| - "execution_count": 15, |
| 116 | + "execution_count": 5, |
147 | 117 | "metadata": {},
|
148 | 118 | "outputs": [
|
149 | 119 | {
|
150 | 120 | "data": {
|
151 | 121 | "text/plain": [
|
152 |
| - "matrix([[ 0., 10., 3., 0.],\n", |
153 |
| - " [ 0., 0., 5., 0.],\n", |
154 |
| - " [ 0., 0., 0., 7.],\n", |
155 |
| - " [ 4., 0., 6., 0.]])" |
| 122 | + "array([ 1, -3, -1], dtype=int32)" |
156 | 123 | ]
|
157 | 124 | },
|
158 |
| - "execution_count": 15, |
| 125 | + "execution_count": 5, |
159 | 126 | "metadata": {},
|
160 | 127 | "output_type": "execute_result"
|
161 | 128 | }
|
162 | 129 | ],
|
163 | 130 | "source": [
|
164 |
| - "w = sparse.dok_matrix((4, 4))\n", |
165 |
| - "\n", |
166 |
| - "edges = [(0, 1, 10), (1, 2, 5), (0, 2, 3),\n", |
167 |
| - " (2, 3, 7), (3, 0, 4), (3, 2, 6)]\n", |
168 |
| - "\n", |
169 |
| - "for i, j, v in edges:\n", |
170 |
| - " w[i, j] = v\n", |
171 |
| - "\n", |
172 |
| - "w.todense()" |
| 131 | + " import numpy as np\n", |
| 132 | + "from scipy.sparse import csr_matrix\n", |
| 133 | + "A = csr_matrix([[1, 2, 0], [0, 0, 3], [4, 0, 5]])\n", |
| 134 | + "v = np.array([1, 0, -1])\n", |
| 135 | + "A.dot(v)" |
| 136 | + ] |
| 137 | + }, |
| 138 | + { |
| 139 | + "cell_type": "markdown", |
| 140 | + "metadata": {}, |
| 141 | + "source": [ |
| 142 | + "#### 示例1" |
| 143 | + ] |
| 144 | + }, |
| 145 | + { |
| 146 | + "cell_type": "markdown", |
| 147 | + "metadata": {}, |
| 148 | + "source": [ |
| 149 | + "构造一个1000x1000 lil_matrix并添加值:" |
173 | 150 | ]
|
174 | 151 | },
|
175 | 152 | {
|
176 | 153 | "cell_type": "code",
|
177 |
| - "execution_count": 17, |
| 154 | + "execution_count": 6, |
178 | 155 | "metadata": {},
|
179 |
| - "outputs": [ |
180 |
| - { |
181 |
| - "ename": "IndexError", |
182 |
| - "evalue": "index 0 is out of bounds for axis 0 with size 0", |
183 |
| - "output_type": "error", |
184 |
| - "traceback": [ |
185 |
| - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
186 |
| - "\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)", |
187 |
| - "\u001b[1;32m<ipython-input-17-c7c2ac13b02d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mH\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mW\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mbimg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 7\u001b[1;33m \u001b[0mx0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwhere\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbimg\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mH\u001b[0m\u001b[1;33m//\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m==\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;31m#❷\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 8\u001b[0m \u001b[0mbimg\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mH\u001b[0m\u001b[1;33m//\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m:\u001b[0m\u001b[0mx0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[0mbimg\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mH\u001b[0m\u001b[1;33m//\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", |
188 |
| - "\u001b[1;31mIndexError\u001b[0m: index 0 is out of bounds for axis 0 with size 0" |
189 |
| - ] |
190 |
| - } |
191 |
| - ], |
| 156 | + "outputs": [], |
192 | 157 | "source": [
|
193 |
| - "img = pl.imread(\"maze.jpg\")\n", |
194 |
| - "sx, sy = (400, 979)\n", |
195 |
| - "ex, ey = (398, 25)\n", |
196 |
| - "bimg = np.all(img > 0.81, axis=2) #❶\n", |
197 |
| - "H, W = bimg.shape\n", |
198 |
| - "\n", |
199 |
| - "x0, x1 = np.where(bimg[H//2, :]==0)[0][[0, -1]] #❷\n", |
200 |
| - "bimg[H//2, :x0] = 0\n", |
201 |
| - "bimg[H//2, x1:] = 0" |
| 158 | + "from scipy.sparse import lil_matrix\n", |
| 159 | + "from scipy.sparse.linalg import spsolve\n", |
| 160 | + "from numpy.linalg import solve, norm\n", |
| 161 | + "from numpy.random import rand" |
202 | 162 | ]
|
203 | 163 | },
|
204 | 164 | {
|
205 | 165 | "cell_type": "code",
|
206 |
| - "execution_count": 18, |
| 166 | + "execution_count": 7, |
207 | 167 | "metadata": {},
|
208 | 168 | "outputs": [],
|
209 | 169 | "source": [
|
210 |
| - "#上下相邻白色像素\n", |
211 |
| - "mask = (bimg[1:, :] & bimg[:-1, :]) \n", |
212 |
| - "idx = np.where(mask.ravel())[0]\n", |
213 |
| - "vedge = np.c_[idx, idx + W]\n", |
214 |
| - "pl.imsave(\"tmp.png\", mask, cmap=\"gray\")\n", |
215 |
| - "\n", |
216 |
| - "#左右相邻白色像素\n", |
217 |
| - "mask = (bimg[:, 1:] & bimg[:, :-1])\n", |
218 |
| - "y, x = np.where(mask)\n", |
219 |
| - "idx = y * W + x\n", |
220 |
| - "hedge = np.c_[idx, idx + 1]\n", |
221 |
| - "\n", |
222 |
| - "edges = np.vstack([vedge, hedge]) #❶\n", |
223 |
| - "\n", |
224 |
| - "values = np.ones(edges.shape[0])\n", |
225 |
| - "w = sparse.coo_matrix((values, (edges[:, 0], edges[:, 1])), #❷\n", |
226 |
| - " shape=(bimg.size, bimg.size))" |
| 170 | + "A = lil_matrix((1000, 1000))\n", |
| 171 | + "A[0, :100] = rand(100)\n", |
| 172 | + "A[1, 100:200] = A[0, :100]\n", |
| 173 | + "A.setdiag(rand(1000))" |
| 174 | + ] |
| 175 | + }, |
| 176 | + { |
| 177 | + "cell_type": "markdown", |
| 178 | + "metadata": {}, |
| 179 | + "source": [ |
| 180 | + "现在将其转换为CSR格式,并求解$A x = b$的$x$:" |
227 | 181 | ]
|
228 | 182 | },
|
229 | 183 | {
|
230 | 184 | "cell_type": "code",
|
231 |
| - "execution_count": 19, |
| 185 | + "execution_count": 8, |
| 186 | + "metadata": {}, |
| 187 | + "outputs": [], |
| 188 | + "source": [ |
| 189 | + "A = A.tocsr()\n", |
| 190 | + "b = rand(1000)\n", |
| 191 | + "x = spsolve(A, b)" |
| 192 | + ] |
| 193 | + }, |
| 194 | + { |
| 195 | + "cell_type": "markdown", |
| 196 | + "metadata": {}, |
| 197 | + "source": [ |
| 198 | + "将其转换为密集矩阵并求解,并检查结果是否相同:" |
| 199 | + ] |
| 200 | + }, |
| 201 | + { |
| 202 | + "cell_type": "code", |
| 203 | + "execution_count": 9, |
| 204 | + "metadata": {}, |
| 205 | + "outputs": [], |
| 206 | + "source": [ |
| 207 | + "x_ = solve(A.toarray(), b)" |
| 208 | + ] |
| 209 | + }, |
| 210 | + { |
| 211 | + "cell_type": "markdown", |
232 | 212 | "metadata": {},
|
233 |
| - "outputs": [ |
234 |
| - { |
235 |
| - "name": "stdout", |
236 |
| - "output_type": "stream", |
237 |
| - "text": [ |
238 |
| - "(1, 801600)\n", |
239 |
| - "(1, 801600)\n" |
240 |
| - ] |
241 |
| - } |
242 |
| - ], |
243 | 213 | "source": [
|
244 |
| - "from scipy.sparse import csgraph\n", |
245 |
| - "startid = sy * W + sx\n", |
246 |
| - "endid = ey * W + ex\n", |
247 |
| - "d, p = csgraph.dijkstra(w, indices=[startid], return_predecessors=True, directed=False)\n", |
248 |
| - "print(d.shape)\n", |
249 |
| - "print(p.shape)" |
| 214 | + "现在我们可以使用以下公式计算错误的范数:" |
250 | 215 | ]
|
251 | 216 | },
|
252 | 217 | {
|
253 | 218 | "cell_type": "code",
|
254 |
| - "execution_count": 20, |
| 219 | + "execution_count": 10, |
255 | 220 | "metadata": {},
|
256 | 221 | "outputs": [
|
257 | 222 | {
|
258 | 223 | "data": {
|
259 | 224 | "text/plain": [
|
260 |
| - "110" |
| 225 | + "True" |
261 | 226 | ]
|
262 | 227 | },
|
263 |
| - "execution_count": 20, |
| 228 | + "execution_count": 10, |
264 | 229 | "metadata": {},
|
265 | 230 | "output_type": "execute_result"
|
266 | 231 | }
|
267 | 232 | ],
|
268 | 233 | "source": [
|
269 |
| - "np.isinf(d[0]).sum()" |
| 234 | + "err = norm(x-x_)\n", |
| 235 | + "err < 1e-10" |
270 | 236 | ]
|
271 | 237 | },
|
272 | 238 | {
|
273 |
| - "cell_type": "code", |
274 |
| - "execution_count": 21, |
| 239 | + "cell_type": "markdown", |
275 | 240 | "metadata": {},
|
276 |
| - "outputs": [], |
277 | 241 | "source": [
|
278 |
| - "path = []\n", |
279 |
| - "node_id = endid\n", |
280 |
| - "while True:\n", |
281 |
| - " path.append(node_id)\n", |
282 |
| - " if node_id == startid or node_id < 0:\n", |
283 |
| - " break\n", |
284 |
| - " node_id = p[0, node_id]\n", |
285 |
| - "path = np.array(path)" |
| 242 | + "#### 示例2\n", |
| 243 | + "构造COO格式的矩阵:" |
286 | 244 | ]
|
287 | 245 | },
|
288 | 246 | {
|
289 | 247 | "cell_type": "code",
|
290 |
| - "execution_count": 22, |
| 248 | + "execution_count": 11, |
291 | 249 | "metadata": {},
|
292 |
| - "outputs": [ |
293 |
| - { |
294 |
| - "ename": "ValueError", |
295 |
| - "evalue": "assignment destination is read-only", |
296 |
| - "output_type": "error", |
297 |
| - "traceback": [ |
298 |
| - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", |
299 |
| - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", |
300 |
| - "\u001b[1;32m<ipython-input-22-8e148d29628c>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m#%figonly=用dijkstra计算最短路径\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpath\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0mW\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpath\u001b[0m \u001b[1;33m//\u001b[0m \u001b[0mW\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mimg\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0mfig\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpl\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplots\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfigsize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m16\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m12\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0maxes\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mimshow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mimg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", |
301 |
| - "\u001b[1;31mValueError\u001b[0m: assignment destination is read-only" |
302 |
| - ] |
303 |
| - } |
304 |
| - ], |
| 250 | + "outputs": [], |
305 | 251 | "source": [
|
306 |
| - "#%figonly=用dijkstra计算最短路径\n", |
307 |
| - "x, y = path % W, path // W\n", |
308 |
| - "img[y, x, :] = 0\n", |
309 |
| - "fig, axes = pl.subplots(1, 2, figsize=(16, 12))\n", |
310 |
| - "axes[0].imshow(img)\n", |
311 |
| - "axes[1].imshow(bimg, cmap=\"gray\")\n", |
312 |
| - "for ax in axes:\n", |
313 |
| - " ax.axis(\"off\")\n", |
314 |
| - "fig.subplots_adjust(0, 0, 1, 1, 0, 0)" |
| 252 | + "from scipy import sparse\n", |
| 253 | + "from numpy import array\n", |
| 254 | + "I = array([0,3,1,0])\n", |
| 255 | + "J = array([0,3,1,2])\n", |
| 256 | + "V = array([4,5,7,9])\n", |
| 257 | + "A = sparse.coo_matrix((V,(I,J)),shape=(4,4))" |
315 | 258 | ]
|
316 | 259 | },
|
317 | 260 | {
|
318 | 261 | "cell_type": "markdown",
|
319 | 262 | "metadata": {},
|
320 | 263 | "source": [
|
321 |
| - "> **SOURCE**\n", |
| 264 | + "注意,索引不需要排序。\n", |
322 | 265 | "\n",
|
323 |
| - "> `scpy2.scipy.hrd_solver`使用`csgraph`计算华容道游戏【横刀立马】布局步数最少的解法。" |
| 266 | + "转换为CSR或CSC时,将对重复的(i,j)条目进行求和。" |
324 | 267 | ]
|
325 | 268 | },
|
326 | 269 | {
|
327 | 270 | "cell_type": "code",
|
328 |
| - "execution_count": 1, |
| 271 | + "execution_count": 12, |
329 | 272 | "metadata": {},
|
330 | 273 | "outputs": [],
|
331 | 274 | "source": [
|
332 |
| - "#%hide\n", |
333 |
| - "%exec_python -m scpy2.scipy.hrd_solver" |
| 275 | + "I = array([0,0,1,3,1,0,0])\n", |
| 276 | + "J = array([0,2,1,3,1,0,0])\n", |
| 277 | + "V = array([1,1,1,1,1,1,1])\n", |
| 278 | + "B = sparse.coo_matrix((V,(I,J)),shape=(4,4)).tocsr()" |
| 279 | + ] |
| 280 | + }, |
| 281 | + { |
| 282 | + "cell_type": "markdown", |
| 283 | + "metadata": {}, |
| 284 | + "source": [ |
| 285 | + "这对于构造有限元刚度矩阵和质量矩阵是有用的。" |
334 | 286 | ]
|
335 | 287 | }
|
336 | 288 | ],
|
|
350 | 302 | "name": "python",
|
351 | 303 | "nbconvert_exporter": "python",
|
352 | 304 | "pygments_lexer": "ipython3",
|
353 |
| - "version": "3.6.4" |
| 305 | + "version": "3.7.3" |
354 | 306 | }
|
355 | 307 | },
|
356 | 308 | "nbformat": 4,
|
|
0 commit comments