回答編集履歴

3

2018/10/17 05:58

投稿

tiitoi
tiitoi

スコア21956

test CHANGED
@@ -188,7 +188,7 @@
188
188
 
189
189
 
190
190
 
191
- for i, j in np.dstack(np.mgrid[1:Nx, 1:Ny]).reshape(-1, 2):
191
+ for i, j in np.dstack(np.mgrid[1:Nx+1, 1:Ny+1]).reshape(-1, 2):
192
192
 
193
193
  E[i - 1, j - 1] = -np.cos(S_pad[i, j] - S_pad[i - 1, j]) \
194
194
 
@@ -201,3 +201,199 @@
201
201
  print(E)
202
202
 
203
203
  ```
204
+
205
+
206
+
207
+ ## 追記
208
+
209
+
210
+
211
+ 話を簡単にするため (3, 3) 行列で考えます。
212
+
213
+
214
+
215
+ ```python
216
+
217
+ Nx, Ny = 3, 3
218
+
219
+ S = np.random.randint(0, 5, (Nx, Ny))
220
+
221
+ print(S)
222
+
223
+ # [[0 2 4]
224
+
225
+ # [0 0 3]
226
+
227
+ # [2 0 2]]
228
+
229
+ ```
230
+
231
+
232
+
233
+ S_pad は (Nx, Ny) の配列の周囲に1ずつパディングを入れたものです。
234
+
235
+ パディングの値は padding='wrap' を指定することで、例えば、S[0, 0] であれば、S[2, 2] の値になるようにしています。
236
+
237
+ これにより、E[0, 0] = -cos(S[0, 0] - S[-1, 0]) を計算する場合、条件分岐が不要になります。
238
+
239
+
240
+
241
+ ```python
242
+
243
+ S_pad = np.pad(a, (1, 1), 'wrap')
244
+
245
+ print(S_pad)
246
+
247
+ # [[2 2 0 2 2]
248
+
249
+ # [4 0 2 4 0]
250
+
251
+ # [3 0 0 3 0]
252
+
253
+ # [2 2 0 2 2]
254
+
255
+ # [4 0 2 4 0]]
256
+
257
+ ```
258
+
259
+
260
+
261
+ S_pad の各要素のインデックスは以下のようになっています。
262
+
263
+
264
+
265
+ ```python
266
+
267
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
268
+
269
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
270
+
271
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
272
+
273
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
274
+
275
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
276
+
277
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
278
+
279
+ (0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4)
280
+
281
+ ```
282
+
283
+
284
+
285
+ このうち、元の行列 S の値がある以下のインデックスだけ iterate したいわけです。
286
+
287
+
288
+
289
+ ```python
290
+
291
+ (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
292
+
293
+ (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
294
+
295
+ (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
296
+
297
+ (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
298
+
299
+ (1, 4) (2, 4) (3, 4) (4, 4) (5, 4)
300
+
301
+ ```
302
+
303
+
304
+
305
+ なので、目標は以下の配列を作ることです。
306
+
307
+
308
+
309
+ ```
310
+
311
+ [(1, 1), (1, 2), (1, 3), (1, 4), ...]
312
+
313
+ ```
314
+
315
+
316
+
317
+ np.mgrid は返り値として次の2つの値を返します。
318
+
319
+
320
+
321
+ ```python
322
+
323
+ X, Y = np.mgrid[1:Nx + 1, 1:Ny + 1]
324
+
325
+ print(X)
326
+
327
+ # 各要素の行
328
+
329
+ # [[1 1 1]
330
+
331
+ # [2 2 2]
332
+
333
+ # [3 3 3]]
334
+
335
+
336
+
337
+ # 各要素の列
338
+
339
+ print(Y)
340
+
341
+ # [[1 2 3]
342
+
343
+ # [1 2 3]
344
+
345
+ # [1 2 3]]
346
+
347
+ ```
348
+
349
+
350
+
351
+ よって、これを np.dstack() で結合すると、各要素のインデックスの一覧が作れます。
352
+
353
+
354
+
355
+ ```python
356
+
357
+ XY = np.dstack([X, Y])
358
+
359
+ print(XY)
360
+
361
+ # [[[1 1] [1 2] [1 3]]
362
+
363
+ # [[2 1] [2 2] [2 3]]
364
+
365
+ # [[3 1] [3 2] [3 3]]]
366
+
367
+ ```
368
+
369
+
370
+
371
+ これは (3, 3, 2) の numpy 配列なので、(9, 2) として、reshape() します。
372
+
373
+ (3, 3, 2) を (9, 2) に reshape() する際に、(?, 2) と2が決まっていれば、? の部分は9と確定するので、この場合、-1 と指定しておくことができます。
374
+
375
+
376
+
377
+ ```python
378
+
379
+ print(XY.reshape(-1, 2)) # XY.reshape(9, 2) と一緒
380
+
381
+ # [[1 1]
382
+
383
+ # [1 2]
384
+
385
+ # [1 3]
386
+
387
+ # [2 1]
388
+
389
+ # [2 2]
390
+
391
+ # [2 3]
392
+
393
+ # [3 1]
394
+
395
+ # [3 2]
396
+
397
+ # [3 3]]
398
+
399
+ ```

2

a

2018/10/17 05:58

投稿

tiitoi
tiitoi

スコア21956

test CHANGED
@@ -109,3 +109,95 @@
109
109
  ...
110
110
 
111
111
  ```
112
+
113
+
114
+
115
+ ## 追記
116
+
117
+
118
+
119
+ 境界条件って端の場合は反対側の値を使うということですよね。
120
+
121
+ であれば、padding='wrap' で [np.pad()](https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.pad.html) しておけばいいです。
122
+
123
+
124
+
125
+ どういうことかは以下を見ていただければわかるかと思います。
126
+
127
+
128
+
129
+ ```
130
+
131
+ a = np.random.randint(0, 5, (5, 5))
132
+
133
+ print(a)
134
+
135
+ # [[3 3 2 2 0]
136
+
137
+ # [0 4 1 2 1]
138
+
139
+ # [1 4 4 1 4]
140
+
141
+ # [4 4 2 4 0]
142
+
143
+ # [4 1 4 3 3]]
144
+
145
+
146
+
147
+ b = np.pad(a, (1, 1), 'wrap')
148
+
149
+ print(b)
150
+
151
+ # [[3 4 1 4 3 3 4]
152
+
153
+ # [0 3 3 2 2 0 3]
154
+
155
+ # [1 0 4 1 2 1 0]
156
+
157
+ # [4 1 4 4 1 4 1]
158
+
159
+ # [0 4 4 2 4 0 4]
160
+
161
+ # [3 4 1 4 3 3 4]
162
+
163
+ # [0 3 3 2 2 0 3]]
164
+
165
+ ```
166
+
167
+
168
+
169
+ ```python
170
+
171
+ np.set_printoptions(linewidth=120)
172
+
173
+
174
+
175
+ Nx, Ny = 5, 5
176
+
177
+ S = np.random.uniform(0, 2 * np.pi, (5, 5))
178
+
179
+ print(S)
180
+
181
+
182
+
183
+ E = np.empty_like(S)
184
+
185
+ S_pad = np.pad(S, (1, 1), 'wrap')
186
+
187
+ print(S_pad)
188
+
189
+
190
+
191
+ for i, j in np.dstack(np.mgrid[1:Nx, 1:Ny]).reshape(-1, 2):
192
+
193
+ E[i - 1, j - 1] = -np.cos(S_pad[i, j] - S_pad[i - 1, j]) \
194
+
195
+ - np.cos(S_pad[i, j] - S_pad[i + 1, j]) \
196
+
197
+ - np.cos(S_pad[i, j] - S_pad[i, j + 1]) \
198
+
199
+ - np.cos(S_pad[i, j] - S_pad[i, j - 1])
200
+
201
+ print(E)
202
+
203
+ ```

1

a

2018/10/17 05:05

投稿

tiitoi
tiitoi

スコア21956

test CHANGED
@@ -23,3 +23,89 @@
23
23
 
24
24
 
25
25
  とするよう書いてあります。
26
+
27
+
28
+
29
+ ## 追記
30
+
31
+
32
+
33
+ 前回の回答で dstack() を使用したのは、「各要素をナンバリングした行列を作りたい」と書いてあったので、np.mgrid で各要素の x 座標と y 座標の一覧を作成し、それを結合するために使いました。
34
+
35
+
36
+
37
+ ```
38
+
39
+ indices = np.dstack(np.mgrid[1:9, 1:9]).reshape(-1, 2)
40
+
41
+ print(indices)
42
+
43
+ ```
44
+
45
+
46
+
47
+ ```
48
+
49
+ [[1 1]
50
+
51
+ [1 2]
52
+
53
+ [1 3]
54
+
55
+ [1 4]
56
+
57
+ [1 5]
58
+
59
+ [1 6]
60
+
61
+ [1 7]
62
+
63
+ ...
64
+
65
+ ```
66
+
67
+
68
+
69
+ ただ、各要素を iteratate するのが目的だったのであれば、np.ndenumerate() を使ったほうがシンプルです。
70
+
71
+
72
+
73
+ ```python
74
+
75
+ a = np.random.randn(5, 5)
76
+
77
+ print(a)
78
+
79
+
80
+
81
+ for index, value in np.ndenumerate(a):
82
+
83
+ print(index, value)
84
+
85
+ ```
86
+
87
+
88
+
89
+ ```
90
+
91
+ [[1 1]
92
+
93
+ [1 2]
94
+
95
+ [1 3]
96
+
97
+ [1 4]
98
+
99
+ [1 5]
100
+
101
+ [1 6]
102
+
103
+ [1 7]
104
+
105
+ [1 8]
106
+
107
+ [2 1]
108
+
109
+ ...
110
+
111
+ ```