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

質問編集履歴

1

追加

2020/11/12 22:26

投稿

apeirogon0813
apeirogon0813

スコア117

title CHANGED
File without changes
body CHANGED
@@ -90,4 +90,183 @@
90
90
 
91
91
  上記は[こちらのサイト](https://ics.media/entry/7298/)を元にselenium部分を追加しました。
92
92
 
93
- ご教示願います。
93
+ ご教示願います。
94
+
95
+ ```python
96
+ import random
97
+ import networkx as nx
98
+ import matplotlib.pyplot as plt
99
+ import copy
100
+
101
+ #要素が重複しているか
102
+ def has_duplicates(seq):
103
+ return len(seq) == len(set(seq))
104
+
105
+ def create_volumes(n):
106
+ #重複しないレコードの作成
107
+ V = random.sample(range(5,260), k=n)
108
+ #観測されるボリューム集合の生成
109
+ W = copy.copy(V)
110
+ for i in range(N-1):
111
+ W.append(V[i]+V[i+1])
112
+ return V, W
113
+
114
+ #候補解から生成されるボリュームを観測したボリュームと比較
115
+ def compare_volumes(S, W):
116
+ T = set()
117
+ #観測されるボリューム集合の生成
118
+ for s in S:
119
+ w = copy.copy(s)
120
+ for i in range(N-1):
121
+ w.append(s[i]+s[i+1])
122
+ if set(w) == set(W):
123
+ #print(tuple(s))
124
+ T.add(tuple(s))
125
+ return T
126
+
127
+
128
+ #1つ以上重複しているボリュームを作成(レコードは重複していない)
129
+ def create_duplicates(n):
130
+ data = create_volumes(n)
131
+ if has_duplicates(data[1]): #重複していないならば
132
+ return create_duplicates(n)
133
+ else:
134
+ return data
135
+
136
+ def create_no_duplicates(n):
137
+ data = create_volumes(n)
138
+ #print(data[1])
139
+ if has_duplicates(data[1]):
140
+ return data
141
+ else:
142
+ return create_duplicates(n)
143
+
144
+
145
+ Ans = []
146
+ N = 26 #攻撃者は既知
147
+ result = create_duplicates(N)
148
+ #result = create_no_duplicates(N)
149
+ V = result[0] #復元したいレコード
150
+ print("V = " + str(V))
151
+ print("W = " + str(result[1]))
152
+ W = list(set(result[1])) #攻撃者が観測するボリュームの集合
153
+
154
+
155
+ #要素を昇順に
156
+ W.sort()
157
+ print("昇順W = " + str(W) + " ( |W| = " + str(len(W)) +" )")
158
+
159
+ G = nx.Graph()
160
+ #step1 2頂点の和がボリュームに含まれているのならエッジを追加
161
+ #連結しているて頂点のみをエッジごと抽出
162
+ n = len(W)
163
+ for i in range(n-2):
164
+ for j in range(i+1,n-1):
165
+ if W[i] + W[j] in W:
166
+ G.add_edge(W[i], W[j])
167
+
168
+ print("存在する枝 = " + str(G.edges))
169
+ print("抽出されたボリューム(" + str(len(G.nodes)) +"/" + str(len(W)) +") = " + str(G.nodes))
170
+ print(list(G.neighbors(W[0])))
171
+
172
+ #step2 確定レコード選別する
173
+ RNodes = [W[0], W[1]] #レコードは重複しない仮定より1,2番目に小さいボリュームはレコードである
174
+ for i in range(2, N):
175
+ for j in range(i):
176
+ #print("W[i] - W[j] = " + str(W[i]) + " - " + str(W[j]))
177
+ if W[i] - W[j] in W and W[i] != 2 * W[j] : #あるボリュームが確定レコード同士の和である時(その要素が隣同士orレコードであるor両方)
178
+ break
179
+ #else: 和でない場合は次に進める
180
+ #最終的にそのボリュームを生成する確定レコードの2要素の和が存在しない場合、そのボリューム確定レコード
181
+ if j == i-1:
182
+ RNodes.append(W[i])
183
+
184
+ print("確定レコード = " + str(RNodes))
185
+
186
+
187
+
188
+ #step3 確定レコードである頂点を通る経路長=N-1である経路
189
+ S = []
190
+ #//集合の中にリストの集合
191
+ l = list(G.neighbors(W[0]))
192
+
193
+ for i in l: #一次元配列だとループが回せないため、二次元配列にしておく
194
+ S.append([W[0],i])
195
+
196
+ def right_shift(S,G):
197
+ #print("S = " + str(S))
198
+ for i in range(N-2): #解の長さがNになるまで
199
+ T = []
200
+ for s in S: #解の数
201
+ if len(s) != N:
202
+ right_num = len(s) - 1
203
+ l = list(G.neighbors(s[right_num]))#一番右の要素と隣合うノードを取得
204
+ for node in l:
205
+ if node not in s: #同じレコードは存在しないかの判定
206
+ C = copy.copy(s)
207
+ C.append(node)
208
+ if C not in T:
209
+ T.append(C)
210
+ T.append(s)#右に拡張できるがそのノードが終点である可能性があるため
211
+ #print(T)
212
+ S = copy.copy(T)
213
+ #print("S = " + str(S))
214
+ return S
215
+
216
+ #S = right_shift(S)
217
+
218
+ #左に拡張
219
+ def left_shift(S,G):
220
+ for i in range(N-2):
221
+ T = []
222
+ for s in S:
223
+ #print("s = " + str(s))
224
+ if len(s) != N:
225
+ l = list(G.neighbors(s[0]))
226
+ for node in l:
227
+ if node not in s: #同じレコードは存在しないかの判定
228
+ C = copy.copy(s)
229
+ C.insert(0,node) #先頭に要素を追加
230
+ if C not in T:
231
+ T.append(C)
232
+ T.append(s)
233
+ S = copy.copy(T)
234
+ #print("s = " + str(S))
235
+ return S
236
+
237
+ #step4 確定コードが解に含まれているか 現段階では確定レコードを通る効率的なアルゴリズムが考えられていないため
238
+ def confirm(S):
239
+ T = []
240
+ for s in S:
241
+ if len(s) == N:
242
+ for i in range(len(RNodes)):
243
+ if RNodes[i] not in s:
244
+ break
245
+ if i == len(RNodes)-1:
246
+ T.append(s)
247
+ return T
248
+ T = copy.copy(S)
249
+ T = right_shift(T,G)
250
+ T = left_shift(T,G)
251
+ S = left_shift(S,G)
252
+ S = right_shift(S,G)
253
+ #print("解候補 = " + str(T))
254
+ print("解の数1 = " + str(len(T)))
255
+ T = confirm(T)
256
+ S = confirm(S)
257
+ #print("解候補選別T = " + str(T))
258
+ #print("解候補選別S = " + str(S))
259
+ print("解の数2 = " + str(len(T)))
260
+
261
+
262
+ #step5 解からボリュームを計算し比較
263
+ G1 = compare_volumes(T, W)
264
+ #print("G1 = " + str(G1))
265
+ G2 = compare_volumes(S, W)
266
+ #print("G2 = " + str(G2))
267
+ G3 = G1|G2
268
+
269
+ print("候補解(" + str(len(G3)) + "個) = " + str(G3))
270
+ print("真の解 = " + str(V))
271
+
272
+ ```