xFS-bots 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. xFS_bots/graph_models/__init__.py +0 -0
  2. xFS_bots/graph_models/_mg_sample.py +331 -0
  3. xFS_bots/graph_models/action_table.py +395 -0
  4. xFS_bots/graph_models/agent_database.py +77 -0
  5. xFS_bots/graph_models/analog_graph.py +130 -0
  6. xFS_bots/graph_models/analog_schemes.py +320 -0
  7. xFS_bots/graph_models/analog_schemes_aux.py +294 -0
  8. xFS_bots/graph_models/base_node.py +189 -0
  9. xFS_bots/graph_models/bfs.py +69 -0
  10. xFS_bots/graph_models/community.py +389 -0
  11. xFS_bots/graph_models/controverter.py +274 -0
  12. xFS_bots/graph_models/cyclical_navigator.py +241 -0
  13. xFS_bots/graph_models/dependency_seq.py +61 -0
  14. xFS_bots/graph_models/dfs.py +78 -0
  15. xFS_bots/graph_models/dir_imp_path.py +188 -0
  16. xFS_bots/graph_models/eb_graph_navigator.py +326 -0
  17. xFS_bots/graph_models/expr_tree.py +907 -0
  18. xFS_bots/graph_models/game_table.py +129 -0
  19. xFS_bots/graph_models/gcs.py +323 -0
  20. xFS_bots/graph_models/graph_gen.py +462 -0
  21. xFS_bots/graph_models/hg_obj_path.py +421 -0
  22. xFS_bots/graph_models/hg_obj_path_op.py +512 -0
  23. xFS_bots/graph_models/hypergraph.py +221 -0
  24. xFS_bots/graph_models/jamming_graph.py +399 -0
  25. xFS_bots/graph_models/lattice_graph_gen.py +402 -0
  26. xFS_bots/graph_models/micrograph.py +414 -0
  27. xFS_bots/graph_models/modular_graph.py +452 -0
  28. xFS_bots/graph_models/node_navigator_handler.py +31 -0
  29. xFS_bots/graph_models/node_path.py +345 -0
  30. xFS_bots/graph_models/node_priority_function.py +97 -0
  31. xFS_bots/graph_models/node_to_cycle.py +85 -0
  32. xFS_bots/graph_models/path_induction.py +260 -0
  33. xFS_bots/graph_models/pswap_graph.py +440 -0
  34. xFS_bots/graph_models/radial_subgraph.py +106 -0
  35. xFS_bots/graph_models/reactive_simple_graph_rules.py +210 -0
  36. xFS_bots/graph_models/shortest_paths.py +429 -0
  37. xFS_bots/graph_models/shortest_paths_approx.py +461 -0
  38. xFS_bots/graph_models/shortest_paths_type_st.py +119 -0
  39. xFS_bots/graph_models/spanning_tree.py +146 -0
  40. xFS_bots/graph_models/sparse_graph_gen.py +66 -0
  41. xFS_bots/graph_models/tree_gen.py +150 -0
  42. xFS_bots/graph_problems/__init__.py +0 -0
  43. xFS_bots/graph_problems/bkb.py +43 -0
  44. xFS_bots/graph_problems/bkb_ext.py +55 -0
  45. xFS_bots/graph_problems/cb.py +73 -0
  46. xFS_bots/graph_problems/cb_ext.py +61 -0
  47. xFS_bots/graph_problems/drb.py +67 -0
  48. xFS_bots/graph_problems/drb_ext.py +27 -0
  49. xFS_bots/graph_problems/easy_gen.py +429 -0
  50. xFS_bots/graph_problems/easy_gen_default_vars.py +104 -0
  51. xFS_bots/graph_problems/efb.py +145 -0
  52. xFS_bots/graph_problems/efb_ext.py +92 -0
  53. xFS_bots/graph_problems/hfb.py +106 -0
  54. xFS_bots/graph_problems/hfb_ext.py +31 -0
  55. xFS_bots/graph_problems/hte.py +319 -0
  56. xFS_bots/graph_problems/hte_ext.py +165 -0
  57. xFS_bots/graph_problems/ib.py +86 -0
  58. xFS_bots/graph_problems/ib_ext.py +65 -0
  59. xFS_bots/graph_problems/mkb.py +76 -0
  60. xFS_bots/graph_problems/mkb_ext.py +45 -0
  61. xFS_bots/graph_problems/mmb.py +126 -0
  62. xFS_bots/graph_problems/mmb_ext.py +34 -0
  63. xFS_bots/graph_problems/pdib.py +41 -0
  64. xFS_bots/graph_problems/pdib_ext.py +30 -0
  65. xFS_bots/graph_problems/pib.py +138 -0
  66. xFS_bots/graph_problems/pib_ext.py +35 -0
  67. xFS_bots/graph_problems/ptb.py +137 -0
  68. xFS_bots/graph_problems/ptb_ext.py +42 -0
  69. xFS_bots/graph_problems/rnb.py +228 -0
  70. xFS_bots/graph_problems/rnb_ext.py +90 -0
  71. xFS_bots/graph_problems/sb.py +79 -0
  72. xFS_bots/graph_problems/sb_ext.py +67 -0
  73. xFS_bots/graph_problems/sim_solution_search.py +92 -0
  74. xFS_bots/graph_problems/snb.py +115 -0
  75. xFS_bots/graph_problems/snb_ext.py +76 -0
  76. xFS_bots/graph_problems/tftmb.py +54 -0
  77. xFS_bots/graph_problems/tftmb_ext.py +56 -0
  78. xFS_bots/graph_problems/tsb.py +42 -0
  79. xFS_bots/graph_problems/tsb_ext.py +36 -0
  80. xFS_bots/graph_problems/vtb.py +13 -0
  81. xFS_bots/graph_problems/vtb_ext.py +44 -0
  82. xFS_bots/quant/__init__.py +0 -0
  83. xFS_bots/quant/agent_23.py +750 -0
  84. xFS_bots/quant/bool_rules.py +50 -0
  85. xFS_bots/quant/bull_graph.py +434 -0
  86. xFS_bots/quant/ce_agent.py +294 -0
  87. xFS_bots/quant/ce_net.py +228 -0
  88. xFS_bots/quant/cee_map.py +247 -0
  89. xFS_bots/quant/cnf_mask.py +182 -0
  90. xFS_bots/quant/cng.py +243 -0
  91. xFS_bots/quant/controverter_graph.py +247 -0
  92. xFS_bots/quant/default_graph_introproc.py +160 -0
  93. xFS_bots/quant/dual_obj.py +337 -0
  94. xFS_bots/quant/gl_expr_table.py +34 -0
  95. xFS_bots/quant/graph_introspector.py +125 -0
  96. xFS_bots/quant/gt_agent.py +94 -0
  97. xFS_bots/quant/hmm_agent.py +382 -0
  98. xFS_bots/quant/hscript_graph.py +501 -0
  99. xFS_bots/quant/hte_analog_induction.py +81 -0
  100. xFS_bots/quant/hte_aux.py +321 -0
  101. xFS_bots/quant/hte_navigator.py +226 -0
  102. xFS_bots/quant/levenschtein.py +89 -0
  103. xFS_bots/quant/middle_agent.py +221 -0
  104. xFS_bots/quant/middleman_graph.py +346 -0
  105. xFS_bots/quant/mob_graph.py +334 -0
  106. xFS_bots/quant/mutable_ce_net.py +46 -0
  107. xFS_bots/quant/mvec_agent.py +462 -0
  108. xFS_bots/quant/pd_graph.py +318 -0
  109. xFS_bots/quant/pd_inadvertency.py +266 -0
  110. xFS_bots/quant/poison_snt.py +277 -0
  111. xFS_bots/quant/pt_aux.py +346 -0
  112. xFS_bots/quant/qstruct.py +671 -0
  113. xFS_bots/quant/qstruct_aux.py +195 -0
  114. xFS_bots/quant/reactive_graph_introspector.py +103 -0
  115. xFS_bots/quant/rstruct.py +256 -0
  116. xFS_bots/quant/selection_rules.py +227 -0
  117. xFS_bots/quant/simple_hmm_env.py +141 -0
  118. xFS_bots/quant/square_nt.py +94 -0
  119. xFS_bots/quant/static_graph_introspector.py +129 -0
  120. xFS_bots/quant/strangle_form.py +567 -0
  121. xFS_bots/quant/strangle_graph.py +160 -0
  122. xFS_bots/quant/ul_vec_classifier.py +58 -0
  123. xFS_bots/quant/usg_controller.py +84 -0
  124. xFS_bots/quant/vt_graph.py +96 -0
  125. xfs_bots-0.0.1.dist-info/METADATA +208 -0
  126. xfs_bots-0.0.1.dist-info/RECORD +129 -0
  127. xfs_bots-0.0.1.dist-info/WHEEL +5 -0
  128. xfs_bots-0.0.1.dist-info/licenses/LICENSE.txt +19 -0
  129. xfs_bots-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,395 @@
1
+ from morebs2.matrix_methods import *
2
+ from morebs2.search_space_iterator import *
3
+ from morebs2.numerical_generator import modulo_in_range,safe_modulo_in_range,prg_seqsort,prg_seqsort_ties
4
+ from morebs2.point_sorter import rank_sequence
5
+ from .tree_gen import SimpleCounter
6
+ from types import MethodType,FunctionType
7
+ from copy import deepcopy
8
+
9
+
10
+ """
11
+ S := str, comma-separated integers, even non-zero number of integers;
12
+ (agent idn i_j,idn i_j move)*
13
+
14
+ return:
15
+ - dict, agent idn -> move idn.
16
+ """
17
+ def string_to_agent_move_map(S):
18
+ q = string_to_vector(S)
19
+ assert len(q) > 0 and len(q) % 2 == 0
20
+ d = dict()
21
+ for i in range(0,len(q),2):
22
+ a,m = q[i],q[i+1]
23
+ d[a] = m
24
+ return d
25
+
26
+ def agent_move_map_to_string(amap):
27
+ assert type(amap) in {dict,defaultdict}
28
+ if len(amap) == 0: return ""
29
+
30
+ keys = sorted(amap.keys())
31
+ s = ""
32
+ for k in keys:
33
+ s += "{},{},".format(int(k),int(amap[k]))
34
+ return s[:-1]
35
+
36
+ def is_partial_agent_move_map_match(partial,whole):
37
+ for k,v in partial.items():
38
+ if whole[k] == v:
39
+ continue
40
+ return False
41
+ return True
42
+
43
+ def agent_move_map__partial_key_match(S,amap):
44
+ key_matches = []
45
+
46
+ for k in S.keys():
47
+ whole = string_to_agent_move_map(k)
48
+ if is_partial_agent_move_map_match(amap,whole):
49
+ key_matches.append(k)
50
+ return sorted(key_matches)
51
+
52
+ def multi_agent_action_map__zeros(agents,agent2movesize_map,move_idn_counter):
53
+ # assign move identifiers to each agent's moves
54
+ agents = sorted(agents)
55
+ agent2move_map = {}
56
+ for a in agents:
57
+ l = agent2movesize_map[a]
58
+ agent2move_map[a] = [move_idn_counter() for _ in range(l)]
59
+
60
+ q = [agent2movesize_map[a] for a in agents]
61
+ bounds = np.array([np.zeros(len(agents),),q]).T
62
+ start_point = bounds[:,0]
63
+ column_order = [i for i in range(len(q))]
64
+ ssi_hop = np.array(q)
65
+ ssi = SearchSpaceIterator(bounds,start_point,column_order,\
66
+ ssi_hop,cycleOn = False,cycleIs = 0)
67
+
68
+ T = {}
69
+ v = {a:0 for a in agents}
70
+ while not ssi.finished():
71
+ # get the index
72
+ n = next(ssi)
73
+ # get the dict
74
+ d = {agents[i]:agent2move_map[i][int(n_)] for (i,n_) in enumerate(n)}
75
+
76
+ # convert dict to string
77
+ s = agent_move_map_to_string(d)
78
+
79
+ # load element
80
+ T[s] = deepcopy(v)
81
+
82
+ return T,agent2move_map
83
+
84
+ def bracket_assignment_agent_action_payoff(T,agent_idn,agent_moveset,agent_action_value_range,\
85
+ bracket_size_range,prg):
86
+
87
+ actions = sorted(agent_moveset)
88
+ num_brackets = modulo_in_range(int(prg()),bracket_size_range)
89
+ ##print(agent_idn," num brackets: ",num_brackets)
90
+ v = n_partition_for_range(agent_action_value_range,num_brackets)
91
+
92
+ actions = prg_seqsort(actions,prg)
93
+ action_brackets = []
94
+ for i,a2 in enumerate(actions):
95
+ i2 = i % num_brackets
96
+ r2 = v[i2:i2+2]
97
+ action_brackets.append(r2)
98
+
99
+ for (i,a) in enumerate(actions):
100
+ amap = {agent_idn:a}
101
+ keys = agent_move_map__partial_key_match(T,amap)
102
+ r2 = action_brackets[i]
103
+ for k in keys:
104
+ value = round(modulo_in_range(prg(),r2),5)
105
+ T[k][agent_idn] = value
106
+ return
107
+
108
+ """
109
+ table that can be used for (immediate XOR cumulative XOR duration of) payoffs from
110
+ actions by agents.
111
+
112
+ Typically used as container for immediate payoffs.
113
+ """
114
+ class MultiAgentActionTable:
115
+
116
+ """
117
+ agents := set, agent idns
118
+ agent_action_map := dict,
119
+ stringized repr. of (agent idn,move idn) -> agent idn -> value from move.
120
+ """
121
+ def __init__(self,agents,agent_action_map):
122
+ self.agents = agents
123
+ self.agent_action_map = agent_action_map
124
+ self.agent2move_map = None
125
+ self.check_arguments()
126
+ return
127
+
128
+ def __str__(self):
129
+ keys = sorted(self.agent_action_map.keys())
130
+ S = ""
131
+ for k in keys:
132
+ S += self.stringize_action_profile(k) + "\n" + "-" * 50 + "\n"
133
+ return S
134
+
135
+ def __getitem__(self, key):
136
+ if key in self.agent_action_map:
137
+ return self.agent_action_map[key]
138
+ assert False
139
+
140
+ def stringize_action_profile(self,k):
141
+ m2 = string_to_agent_move_map(k)
142
+ x = self.agent_action_map[k]
143
+ keys = sorted(m2.keys())
144
+
145
+ s = ""
146
+ for k2 in keys:
147
+ s += "agent {} move {} value {}\n".format(k2,m2[k2],x[k2])
148
+ return s
149
+
150
+ ################### preprocessing moves for info on `agent_action_map`
151
+ def check_arguments(self):
152
+ assert type(self.agents) == set
153
+ self.agent2move_map = self.agent_to_move_map()
154
+ assert len(self.agent_action_map) == self.total_number_of_move_combinations()
155
+ return
156
+
157
+ def agent_to_move_map(self):
158
+ d = defaultdict(set)
159
+ for k,v in self.agent_action_map.items():
160
+ q = string_to_agent_move_map(k)
161
+ for k2,v2 in q.items():
162
+ d[k2] |= {v2}
163
+ assert type(v) in {dict,defaultdict}
164
+ assert set(v.keys()) == self.agents
165
+ return d
166
+
167
+ def total_number_of_move_combinations(self):
168
+ l = 1
169
+ for v in self.agent2move_map.values():
170
+ l = l * len(v)
171
+ return l
172
+
173
+ ############################## used to determine lattice points of n-dimensional
174
+ ############################## game table prism.
175
+
176
+ """
177
+ sort_index := 0 -> min,
178
+ 1 -> max,
179
+ 2 -> mean.
180
+ """
181
+ def sort_agent_moves(self,a_idn,sort_index,other_agent_moves={}):
182
+ assert sort_index in {0,1,2}
183
+
184
+ move_info = []
185
+ for m in self.agent2move_map[a_idn]:
186
+ info = self.base_info_on_agent_move(a_idn,m,other_agent_moves)
187
+ move_info.append((int(m),info))
188
+ q = sorted(move_info,key=lambda x:x[1][sort_index])
189
+ return [(q_[0],q_[1][sort_index]) for q_ in q]
190
+
191
+ """
192
+ Determines the rank of agent `a_idn` conducting move `move_idn`
193
+ w.r.t. the others. For every element E in `agent_action_map` that
194
+ has agent `a_idn` conduct `move_idn`, ranks value of agent with the
195
+ costs of the other agents, producing rank r.
196
+
197
+ NOTE: ordering of rank is least=0, greatest=max.
198
+
199
+ return:
200
+ - list, ranks of value for agent conducting move w.r.t. other agents.
201
+ """
202
+ def possible_ranks_of_agent_by_move(self,a_idn,move_idn,other_agent_moves={}):
203
+ self.query_parameter_assertion(a_idn,move_idn,other_agent_moves)
204
+
205
+ amap = {a_idn:move_idn}
206
+ amap.update(other_agent_moves)
207
+
208
+ keys = agent_move_map__partial_key_match(self.agent_action_map,amap)
209
+ ranks = []
210
+ for k in keys:
211
+ v = self.agent_action_map[k]
212
+ v_ = [(k2,v2) for k2,v2 in v.items()]
213
+ q = rank_sequence(v_,vf=lambda x:x[1],\
214
+ element_output_function=lambda x:x[0],output_type=dict)
215
+ r = q[a_idn]
216
+ ranks.append(r)
217
+ return ranks
218
+
219
+ """
220
+ return:
221
+ - (min,max,mean) of agent move payoffs
222
+ """
223
+ def base_info_on_agent_move(self,a_idn,move_idn,other_agent_moves={}):
224
+ self.query_parameter_assertion(a_idn,move_idn,other_agent_moves)
225
+
226
+ amap = {a_idn:move_idn}
227
+ amap.update(other_agent_moves)
228
+ keys = agent_move_map__partial_key_match(self.agent_action_map,amap)
229
+ assert len(keys) > 0
230
+
231
+ vs = []
232
+ for k in keys:
233
+ v = self.agent_action_map[k][a_idn]
234
+ vs.append(v)
235
+
236
+ return np.min(vs),np.max(vs),np.round(np.mean(vs),5)
237
+
238
+ """
239
+ calculates the move by agent `a_idn` that would yield the minumum mean paypoff by agents in
240
+ set `other_idns`. If `other_agent_moves` is not empty, only those moves by the other agents
241
+ are considered in the ranking calculation.
242
+ """
243
+ def agent_move_for_minmean_value_by_other_agents(self,a_idn,other_idns,other_agent_moves={},\
244
+ prg = None):
245
+ return self.agent_countermove_for_other_agents(a_idn,other_idns,other_agent_moves,\
246
+ 2,2,prg)
247
+
248
+ """
249
+ Calculates the move by agent that would yield the "minimal" payoff,
250
+ MIN (MIN|MAX|MEAN (MIN|MAX|MEAN(others))),
251
+ by the other agents. See description for
252
+ function<MultiAgentActionTable.agent_move_for_info_on_other_agents> for how this "minimal"
253
+ payoff is calculated.
254
+ """
255
+ def agent_countermove_for_other_agents(self,a_idn,other_idns,other_agent_moves,\
256
+ index0,index1,prg = None):
257
+
258
+ other_info = self.agent_move_for_info_on_other_agents(a_idn,other_idns,other_agent_moves,\
259
+ index0,index1)
260
+ other_info = [(k,v) for k,v in other_info.items()]
261
+
262
+ if type(prg) != type(None):
263
+ return int(prg_seqsort_ties(other_info,prg,vf=lambda x:x[1])[0][0])
264
+ return int(sorted(other_info,key=lambda x:x[1])[0][0])
265
+
266
+ """
267
+ index0 := (0|1|2) <-> (min|max|mean), payoff for other agents
268
+ index1 := (0|1|2) <-> (min|max|mean), summarization (1 value) of other agents' payoff map.
269
+
270
+ return:
271
+ - agent move idn -> payoff info specified by the criteria (index0,index1).
272
+ """
273
+ def agent_move_for_info_on_other_agents(self,a_idn,other_idns,other_agent_moves={},index0=2,\
274
+ index1=2):
275
+ assert index0 in {0,1,2}
276
+ assert index1 in {0,1,2}
277
+
278
+ def fx(S):
279
+ if index1 == 0:
280
+ return np.min(S)
281
+ elif index1 == 1:
282
+ return np.max(S)
283
+ else:
284
+ return np.round(np.mean(S),5)
285
+
286
+ move_info = {}
287
+ for m in self.agent2move_map[a_idn]:
288
+ dx = self.base_info_on_other_agents(a_idn,m,other_idns,other_agent_moves)
289
+ s = [v[index0] for v in dx.values()]
290
+ s = fx(s)
291
+ move_info[m] = s
292
+ return move_info
293
+
294
+ """
295
+ given agent `a_idn` that conducts move `move_idn`, a map
296
+
297
+ other agent idn -> (min,max,mean) payoff values
298
+
299
+ is produced.
300
+ """
301
+ def base_info_on_other_agents(self,a_idn,move_idn,other_idns,other_agent_moves={}):
302
+ self.query_parameter_assertion(a_idn,move_idn,other_agent_moves)
303
+ assert other_idns.issubset(self.agents) and a_idn not in other_idns
304
+
305
+ amap = {a_idn:move_idn}
306
+ amap.update(other_agent_moves)
307
+ keys = agent_move_map__partial_key_match(self.agent_action_map,amap)
308
+ assert len(keys) > 0
309
+
310
+ vs = []
311
+ other_agent_mean = defaultdict(float)
312
+ other_agent_min = {o:float('inf') for o in other_idns}
313
+ other_agent_max = {o:-float('inf') for o in other_idns}
314
+
315
+ for k in keys:
316
+ v = self.agent_action_map[k]
317
+ for o in other_idns:
318
+ v2 = v[o]
319
+ other_agent_mean[o] += v2
320
+ other_agent_min[o] = min([v2,other_agent_min[o]])
321
+ other_agent_max[o] = max([v2,other_agent_max[o]])
322
+ for o in other_idns:
323
+ other_agent_mean[o] = round(other_agent_mean[o] / len(keys),5)
324
+
325
+ other_agent_info = {o:\
326
+ (other_agent_min[o],other_agent_max[o],other_agent_mean[o]) \
327
+ for o in other_idns}
328
+ return other_agent_info
329
+
330
+ def query_parameter_assertion(self,a_idn,move_idn,other_agent_moves):
331
+ assert a_idn in self.agents
332
+ assert move_idn in self.agent2move_map[a_idn]
333
+ assert type(other_agent_moves) == dict
334
+ assert set(other_agent_moves.keys()).issubset(self.agents)
335
+
336
+ @staticmethod
337
+ def generate_instance__type_prng(agents,agent2movesize_map,agent_action_value_range,\
338
+ prg,move_idn_counter=SimpleCounter(0).__next__):
339
+ agent_action_value_range = MultiAgentActionTable.generate_instance__parameter_assertion(\
340
+ agents,agent2movesize_map,agent_action_value_range,prg)
341
+
342
+ T,_ = multi_agent_action_map__zeros(agents,agent2movesize_map,move_idn_counter)
343
+ agents_ = sorted(agents)
344
+
345
+ keys = sorted(T.keys())
346
+ for k in keys:
347
+ v = T[k]
348
+ for k2 in agents_:
349
+ v[k2] = round(safe_modulo_in_range(prg(),\
350
+ agent_action_value_range[k2]),5)
351
+ return MultiAgentActionTable(agents,T)
352
+
353
+ @staticmethod
354
+ def generate_instance__type_strict_percentile(agents,agent2movesize_map,agent_action_value_range,\
355
+ prg,bracket_size_range,move_idn_counter=SimpleCounter(0).__next__):
356
+
357
+ agent_action_value_range = MultiAgentActionTable.generate_instance__parameter_assertion(\
358
+ agents,agent2movesize_map,agent_action_value_range,prg)
359
+
360
+ T,M = multi_agent_action_map__zeros(agents,agent2movesize_map,move_idn_counter)
361
+ agents = sorted(agents)
362
+ for agent_idn in agents:
363
+ agent_moveset = M[agent_idn]
364
+ aarange = agent_action_value_range[agent_idn]
365
+ bracket_assignment_agent_action_payoff(T,agent_idn,agent_moveset,\
366
+ aarange,bracket_size_range,prg)
367
+ return MultiAgentActionTable(set(agents),T)
368
+
369
+ @staticmethod
370
+ def generate_instance__parameter_assertion(agents,agent2movesize_map,agent_action_value_range,\
371
+ prg):
372
+ assert type(prg) in {FunctionType,MethodType}
373
+
374
+ agent_action_value_range = MultiAgentActionTable.format_agent_action_value_range(\
375
+ agents,agent_action_value_range)
376
+
377
+ assert set(agent2movesize_map.keys()) == agents
378
+ for v in agent2movesize_map.values(): assert v > 0
379
+ return agent_action_value_range
380
+
381
+ @staticmethod
382
+ def format_agent_action_value_range(agents,agent_action_value_range):
383
+
384
+ if type(agent_action_value_range) == dict:
385
+ assert set(agent_action_value_range.keys()) == agents
386
+ for v in agent_action_value_range.values():
387
+ assert v[0] <= v[1]
388
+ else:
389
+ assert agent_action_value_range[0] <= agent_action_value_range[1]
390
+ agents = sorted(agents)
391
+ d = {}
392
+ for k in agents:
393
+ d[k] = deepcopy(agent_action_value_range)
394
+ agent_action_value_range = d
395
+ return agent_action_value_range
@@ -0,0 +1,77 @@
1
+ import numpy as np
2
+ from copy import deepcopy
3
+
4
+ class AgentInfo:
5
+
6
+ def __init__(self,info_type):
7
+ assert info_type in {str,int,float,\
8
+ list,set,np.ndarray}
9
+ self.info_type = info_type
10
+ self.info = None
11
+ self.last_info = None
12
+ return
13
+
14
+ def __str__(self):
15
+ return str(self.info)
16
+
17
+ def __add__(self,s):
18
+ assert type(s) == self.info_type, "got {}".format(type(s))
19
+ q = deepcopy(self)
20
+ q.last_info = s
21
+ if type(q.info) == type(None):
22
+ if q.info_type == np.ndarray:
23
+ q.info = np.array([s])
24
+ else:
25
+ q.info = s
26
+ elif q.info_type in {str,int,float}:
27
+ q.info += s
28
+ elif q.info_type == list:
29
+ q.info.append(s)
30
+ elif q.info_type == set:
31
+ q.info |= s
32
+ else:
33
+ q.info = np.vstack((q.info,s))
34
+ return q
35
+
36
+ class SimpleAgentDB:
37
+
38
+ def __init__(self,info_type):
39
+ self.info_type = info_type
40
+ self.agent_idns = []
41
+ self.agent_info = dict()
42
+ self.c = 0
43
+
44
+ def __str__(self):
45
+ S = ""
46
+ for k,v in self.agent_info.items():
47
+ S += str(k) + "\n" + str(v) + "\n\n"
48
+ return S
49
+
50
+ def add_agent(self):
51
+ self.add_agent_(self.c)
52
+ self.c += 1
53
+ return
54
+
55
+ def add_agent_(self,idn):
56
+ assert idn not in self.agent_idns
57
+ self.agent_idns.append(idn)
58
+ self.agent_info[idn] = AgentInfo(self.info_type)
59
+ return
60
+
61
+ def update_info(self,idn,info):
62
+ if idn not in self.agent_idns:
63
+ self.add_agent_(idn)
64
+ self.agent_info[idn] = self.agent_info[idn] + info
65
+ return
66
+
67
+ def last_info_for_agent(self,idn):
68
+ if idn not in self.agent_idns: return None
69
+ return self.agent_info[idn].last_info
70
+
71
+ def delete_agent_info(self,idn):
72
+ if idn not in self.agent_idns: return
73
+
74
+ i = self.agent_idns.index(idn)
75
+ self.agent_idns.pop(i)
76
+ del self.agent_info[idn]
77
+ return
@@ -0,0 +1,130 @@
1
+ from .analog_schemes_aux import *
2
+ from .radial_subgraph import *
3
+
4
+ DEFAULT_ANALOG_GRAPH_SUBGRAPH_RADIUS_RANGE = [1,3]
5
+
6
+ # NOTE: duplicate code?
7
+ def dict_diff(ref_dict, other_dict):
8
+ c = 0
9
+ for k,v in ref_dict.items():
10
+ if k not in other_dict:
11
+ c += 1
12
+ continue
13
+ v2 = other_dict[k]
14
+ if v != v2:
15
+ c += 1
16
+ return c
17
+
18
+
19
+ # TODO: test this.
20
+ """
21
+ reference_graph := defaultdict, graph
22
+ isomap := node of reference graph -> node of another graph
23
+ prg := PRNG
24
+ isomorphic_subgraph_radius_range := range
25
+ """
26
+ class AnalogGraph:
27
+
28
+ def __init__(self,reference_graph,isomap,prg,isomorphic_subgraph_radius_range=DEFAULT_ANALOG_GRAPH_SUBGRAPH_RADIUS_RANGE):
29
+ assert type(reference_graph) == defaultdict
30
+ assert type(isomap) == dict
31
+ assert type(prg) in {MethodType,FunctionType}
32
+ assert is_valid_range(isomorphic_subgraph_radius_range,True,False)
33
+
34
+ self.reference_graph = reference_graph
35
+ self.isomap = isomap
36
+ self.prg = prg
37
+ self.iso_sg_radius_range = isomorphic_subgraph_radius_range
38
+ self.preproc()
39
+ return
40
+
41
+ def preproc(self):
42
+ self.qsf = QuickSubgraphFetcher(self.reference_graph,self.prg)
43
+ return
44
+
45
+ def draw_analogy_to(self,G,exact_node_mapping_ratio:float):
46
+ assert type(G) == defaultdict
47
+ assert 0.0 <= exact_node_mapping_ratio <= 1.0
48
+ #assert AnalogGraph.graph_is_analogical(self.reference_graph,G,self.isomap)
49
+ candidates = sorted(self.isomap.keys())
50
+
51
+ def prg_(): return int(self.prg())
52
+
53
+ num_exact_mapping = ceil(len(candidates) * exact_node_mapping_ratio)
54
+ exact_nodes = prg_choose_n(candidates,num_exact_mapping,prg_,is_unique_picker=True)
55
+
56
+ node_analogy = {}
57
+ got = set()
58
+ def analogical_node(n):
59
+ if n in exact_nodes:
60
+ return self.isomap[n]
61
+
62
+ # fetch the subgraph
63
+ ref_sg = self.subgraph_for_node(n)
64
+ # calculate the isomorphisms
65
+ mg = MicroGraph(ref_sg)
66
+ mg2 = MicroGraph(G)
67
+
68
+ Q = mg2.subgraph_isomorphism(mg,all_iso=True,size_limit=200,search_candidate_limit=50000)#prg=self.prg)
69
+ if len(Q) == 0: return None
70
+
71
+ # approach #1
72
+ """
73
+ # choose an isomorphism
74
+ index = int(self.prg()) % len(Q)
75
+ isomorphism = Q[index]
76
+ print("ISO ",Q[index])
77
+
78
+ isomorphism = {v:k for k,v in isomorphism}
79
+
80
+ if n not in isomorphism: return None
81
+ return isomorphism[n]
82
+ """
83
+
84
+ # approach #2
85
+ qs = []
86
+ for iso in Q:
87
+ iso2 = {v:k for k,v in iso}
88
+ if n not in iso2:
89
+ continue
90
+ qs.append(iso2[n])
91
+
92
+ untaken = set(qs) - got
93
+ if len(untaken) == 0: return None
94
+
95
+ untaken = sorted(untaken)
96
+ index = int(self.prg()) % len(untaken)
97
+ return untaken[index]
98
+
99
+
100
+ for k in self.isomap.keys():
101
+ x = analogical_node(k)
102
+ ##print("analogical node for {}:{}".format(k,x))
103
+ if type(x) != type(None):
104
+ node_analogy[k] = x
105
+ got |= {x}
106
+
107
+ return node_analogy
108
+
109
+ def subgraph_for_node(self,n):
110
+ radius = modulo_in_range(int(self.prg()),self.iso_sg_radius_range)
111
+ return self.qsf.subgraph(n,radius)
112
+
113
+ @staticmethod
114
+ def graph_is_analogical(ref_graph,analogy_graph,isomap):
115
+ for k,v in isomap.items():
116
+ if k not in ref_graph: return False
117
+ if v not in analogy_graph: return False
118
+ return True
119
+
120
+ class AnalogGraphGroup:
121
+
122
+ def __init__(self,analog_graphs,isomaps):
123
+ assert len(analog_graphs) > 1
124
+ assert len(analog_graphs) == len(isomaps) + 1
125
+
126
+ for x in analog_graphs: assert type(x) == AnalogGraph
127
+ for x in isomaps: assert type(x) == dict
128
+ self.analog_graphs = analog_graphs
129
+ self.isomaps = isomaps
130
+ return