質問するログイン新規登録

回答編集履歴

4

コード論理の間違い

2018/05/11 04:23

投稿

KSwordOfHaste
KSwordOfHaste

スコア18406

answer CHANGED
@@ -44,22 +44,17 @@
44
44
  # Pを次々に生成するジェネレーター
45
45
  # Pは5 x 11とする。1の場所は11個の中から5個選ぶ
46
46
  # itertools.permutationsを使えば単純にできるがあえて原始的に実装
47
- # 組み合わせはTC1 x TC2 = (11 * 10 * 9 * 8 * 7 * 5 * 4 * 3 * 2)通り
47
+ # 組み合わせはTC1 = 11 * 10 * 9 * 8 * 7
48
48
  S1 = [i for i in range(11, 6, -1)]
49
- S2 = [i for i in range(5, 0, -1)]
50
49
  TC1 = functools.reduce(operator.mul, S1)
51
- TC2 = functools.reduce(operator.mul, S2)
52
50
 
53
51
  for tc1 in range(TC1):
54
52
  i1 = iii(S1, tc1)
55
- for tc2 in range(TC2):
56
- i2 = iii(S2, tc2)
57
- a = np.zeros((5, 11), dtype=np.uint8)
53
+ a = np.zeros((5, 11), dtype=np.uint8)
58
- # print(f'i1={i1}, i2={i2}')
59
- for i in range(5):
54
+ for i in range(5):
60
- # print(f'i2[i]={i2[i]}, i1[i]={i1[i]}')
55
+ # print(f'i2[i]={i2[i]}, i1[i]={i1[i]}')
61
- a[i2[i], i1[i]] = 1
56
+ a[i, i1[i]] = 1
62
- yield a
57
+ yield a
63
58
 
64
59
  def iii(ss, t):
65
60
  # t番目の組み合わせのインデックスを生成
@@ -74,12 +69,12 @@
74
69
  return r
75
70
 
76
71
  def main():
77
- count = 0
72
+ count = 1
78
73
  g = genp()
79
74
  for p in g:
80
75
  A3 = p.dot(A1).dot(p.T)
81
76
  if np.all(A2 == A3):
82
- print(f'match count={count}')
77
+ print(f'number of trials = {count}')
83
78
  print('p=')
84
79
  print(p)
85
80
  break

3

コードを追記

2018/05/11 04:22

投稿

KSwordOfHaste
KSwordOfHaste

スコア18406

answer CHANGED
@@ -4,4 +4,91 @@
4
4
 
5
5
  p.9にUllmannの方法として「一定の約束事(行や列の順列など)で重複なく置換行列Pを生成する」と有りますが、この方法ではNP完全問題をまともに解く(有り得る様々なPを想定してしらみつぶしに調べてゆく)ということのように思えました。しかしこのページ以降に置換行列Pの大きさをしぼれそうな様々な手法が書かれていますね。
6
6
 
7
- いずれにせよ少なくとも重複なく置換行列Pを生成するという論理が必要と思います。A1の大きさと重みありの個数を見ますと、まともに有り得る置換行列の全ての組み合わせを探索しても`9!×2 = 725760`となりますので素朴に総当たりしても(ご質問にある規模の問題なら)時間的には大丈夫な気がします。
7
+ いずれにせよ少なくとも重複なく置換行列Pを生成するという論理が必要と思います。A1の大きさと重みありの個数を見ますと、まともに有り得る置換行列の全ての組み合わせを探索しても`9!×2 = 725760`となりますので素朴に総当たりしても(ご質問にある規模の問題なら)時間的には大丈夫な気がします。
8
+ (追記:最大30x30を想定しておられるとのことでまともに全探索するアプローチでは不十分と思いました)
9
+
10
+ ---
11
+ 追記:VBAではありませんが、ご要望があったので全探索をするPythonコードを参考までに挙げておきます。
12
+ 適当に書いたままなのであまりよいコードではありませんが。
13
+
14
+ ```Python
15
+ import numpy as np
16
+ import functools
17
+ import operator
18
+
19
+ A1=[
20
+ [0,1,1,1,1,0,0,0,0,0,0],
21
+ [1,0,0,0,0,1,0,0,0,0,0],
22
+ [1,0,0,0,0,0,1,1,1,0,0],
23
+ [1,0,0,0,0,0,0,0,0,0,0],
24
+ [1,0,0,0,0,0,0,0,0,0,0],
25
+ [0,1,0,0,0,0,0,0,0,2,1],
26
+ [0,0,1,0,0,0,0,0,0,0,0],
27
+ [0,0,1,0,0,0,0,0,0,0,0],
28
+ [0,0,1,0,0,0,0,0,0,0,0],
29
+ [0,0,0,0,0,2,0,0,0,0,0],
30
+ [0,0,0,0,0,1,0,0,0,0,0]
31
+ ]
32
+ A2 = [
33
+ [0,1,0,0,0],
34
+ [1,0,1,0,0],
35
+ [0,1,0,2,1],
36
+ [0,0,2,0,0],
37
+ [0,0,1,0,0]
38
+ ]
39
+
40
+ A1 = np.array(A1, dtype=np.uint8)
41
+ A2 = np.array(A2, dtype=np.uint8)
42
+
43
+ def genp():
44
+ # Pを次々に生成するジェネレーター
45
+ # Pは5 x 11とする。1の場所は11個の中から5個選ぶ
46
+ # itertools.permutationsを使えば単純にできるがあえて原始的に実装
47
+ # 組み合わせはTC1 x TC2 = (11 * 10 * 9 * 8 * 7 * 5 * 4 * 3 * 2)通り
48
+ S1 = [i for i in range(11, 6, -1)]
49
+ S2 = [i for i in range(5, 0, -1)]
50
+ TC1 = functools.reduce(operator.mul, S1)
51
+ TC2 = functools.reduce(operator.mul, S2)
52
+
53
+ for tc1 in range(TC1):
54
+ i1 = iii(S1, tc1)
55
+ for tc2 in range(TC2):
56
+ i2 = iii(S2, tc2)
57
+ a = np.zeros((5, 11), dtype=np.uint8)
58
+ # print(f'i1={i1}, i2={i2}')
59
+ for i in range(5):
60
+ # print(f'i2[i]={i2[i]}, i1[i]={i1[i]}')
61
+ a[i2[i], i1[i]] = 1
62
+ yield a
63
+
64
+ def iii(ss, t):
65
+ # t番目の組み合わせのインデックスを生成
66
+ i = [i for i in range(ss[0])]
67
+ r = []
68
+ for s in ss:
69
+ j = t % s
70
+ # print(f'j={j} i={i}')
71
+ r.append(i[j])
72
+ del i[j]
73
+ t //= s
74
+ return r
75
+
76
+ def main():
77
+ count = 0
78
+ g = genp()
79
+ for p in g:
80
+ A3 = p.dot(A1).dot(p.T)
81
+ if np.all(A2 == A3):
82
+ print(f'match count={count}')
83
+ print('p=')
84
+ print(p)
85
+ break
86
+ count += 1
87
+ # 探索の進捗具合の確認用
88
+ if count % 10000 == 0:
89
+ print(f'count={count}')
90
+
91
+ if __name__ == '__main__':
92
+ main()
93
+ ```
94
+ (Python 3.6.5)

2

誤記

2018/05/10 05:41

投稿

KSwordOfHaste
KSwordOfHaste

スコア18406

answer CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  こんなPDFを眺めてみました。p.7にある部分グラフ同型判定のところを見ますとNP完全問題とありました。p.9以降に様々な具体的手法が紹介されていますね。
4
4
 
5
- p.9にUllmannの方法として「一定の約束事(行や列の順列など)で重複なく置換行列Pを生成する」と有りますが、この方法ではNP完全問題をまともに解く(有り得る様々なPを想定してしらみつぶしに調べてゆくしかないということのように思えました。またこのページ以降に置換行列Pの大きさをしぼれそうな様々な手法が書かれていますね。
5
+ p.9にUllmannの方法として「一定の約束事(行や列の順列など)で重複なく置換行列Pを生成する」と有りますが、この方法ではNP完全問題をまともに解く(有り得る様々なPを想定してしらみつぶしに調べてゆく)ということのように思えました。しかしこのページ以降に置換行列Pの大きさをしぼれそうな様々な手法が書かれていますね。
6
6
 
7
7
  いずれにせよ少なくとも重複なく置換行列Pを生成するという論理が必要と思います。A1の大きさと重みありの個数を見ますと、まともに有り得る置換行列の全ての組み合わせを探索しても`9!×2 = 725760`となりますので素朴に総当たりしても(ご質問にある規模の問題なら)時間的には大丈夫な気がします。

1

登録ミス

2018/05/09 05:30

投稿

KSwordOfHaste
KSwordOfHaste

スコア18406

answer CHANGED
File without changes