@@ -80,8 +80,8 @@ namespace hal
80
80
igraph_integer_t i, j, k;
81
81
igraph_bool_t * added;
82
82
igraph_vector_int_t current_hood, previous_hood;
83
- igraph_vector_int_t * chp = ¤t_hood;
84
- igraph_vector_int_t * php = &previous_hood;
83
+ igraph_vector_int_t * current_hood_p = ¤t_hood;
84
+ igraph_vector_int_t * previous_hood_p = &previous_hood;
85
85
igraph_vector_int_t tmp;
86
86
87
87
if (timeout < 0 )
@@ -93,34 +93,34 @@ namespace hal
93
93
IGRAPH_CHECK_OOM (added, " Cannot calculate neighborhood size." );
94
94
IGRAPH_FINALLY (igraph_free, added);
95
95
96
- IGRAPH_VECTOR_INT_INIT_FINALLY (chp , 0 );
97
- IGRAPH_VECTOR_INT_INIT_FINALLY (php , 0 );
96
+ IGRAPH_VECTOR_INT_INIT_FINALLY (current_hood_p , 0 );
97
+ IGRAPH_VECTOR_INT_INIT_FINALLY (previous_hood_p , 0 );
98
98
IGRAPH_VECTOR_INT_INIT_FINALLY (&tmp, 0 );
99
99
100
100
IGRAPH_CHECK (igraph_vector_int_init (in_set, 0 ));
101
101
IGRAPH_CHECK (igraph_vector_int_init (out_set, 0 ));
102
102
igraph_vector_int_clear (in_set);
103
103
igraph_vector_int_clear (out_set);
104
104
105
- IGRAPH_CHECK (igraph_vector_int_push_back (chp , node));
105
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_hood_p , node));
106
106
107
107
igraph_integer_t previous_size, current_size;
108
108
109
109
for (i = 0 ; i < timeout; i++)
110
110
{
111
- previous_size = igraph_vector_int_size (php );
112
- current_size = igraph_vector_int_size (chp );
111
+ previous_size = igraph_vector_int_size (previous_hood_p );
112
+ current_size = igraph_vector_int_size (current_hood_p );
113
113
114
114
if (previous_size < current_size)
115
115
{
116
- IGRAPH_CHECK (igraph_vector_int_swap (php, chp ));
117
- igraph_vector_int_clear (chp );
116
+ IGRAPH_CHECK (igraph_vector_int_swap (previous_hood_p, current_hood_p ));
117
+ igraph_vector_int_clear (current_hood_p );
118
118
119
119
memset (added, false , no_of_nodes * sizeof (igraph_bool_t ));
120
120
121
121
for (j = 0 ; j < current_size; j++)
122
122
{
123
- igraph_integer_t actnode = VECTOR (*php )[j];
123
+ igraph_integer_t actnode = VECTOR (*previous_hood_p )[j];
124
124
igraph_vector_int_clear (&tmp);
125
125
IGRAPH_CHECK (igraph_neighbors (graph, &tmp, actnode, IGRAPH_OUT));
126
126
@@ -130,7 +130,7 @@ namespace hal
130
130
if (!added[nei])
131
131
{
132
132
added[nei] = true ;
133
- IGRAPH_CHECK (igraph_vector_int_push_back (chp , nei));
133
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_hood_p , nei));
134
134
}
135
135
}
136
136
}
@@ -139,22 +139,172 @@ namespace hal
139
139
{
140
140
if (previous_size == current_size)
141
141
{
142
- IGRAPH_CHECK (igraph_vector_int_update (in_set, php ));
143
- IGRAPH_CHECK (igraph_vector_int_update (out_set, chp ));
142
+ IGRAPH_CHECK (igraph_vector_int_update (in_set, previous_hood_p ));
143
+ IGRAPH_CHECK (igraph_vector_int_update (out_set, current_hood_p ));
144
144
}
145
145
146
146
break ;
147
147
}
148
148
}
149
149
150
- igraph_vector_int_destroy (chp );
151
- igraph_vector_int_destroy (php );
150
+ igraph_vector_int_destroy (current_hood_p );
151
+ igraph_vector_int_destroy (previous_hood_p );
152
152
igraph_vector_int_destroy (&tmp);
153
153
IGRAPH_FREE (added);
154
154
IGRAPH_FINALLY_CLEAN (4 );
155
155
156
156
return IGRAPH_SUCCESS;
157
157
}
158
+
159
+ igraph_error_t get_saturating_neighborhoods_scc (const igraph_t * graph,
160
+ igraph_vector_int_t * in_set,
161
+ igraph_vector_int_t * out_set,
162
+ igraph_integer_t node,
163
+ igraph_integer_t timeout,
164
+ std::map<std::set<u32 >, igraph_vector_int_t *>& cache)
165
+ {
166
+ igraph_integer_t no_of_nodes = igraph_vcount (graph);
167
+ igraph_integer_t i, j, k;
168
+ igraph_bool_t * added;
169
+ igraph_vector_int_t current_hood, previous_hood;
170
+ igraph_vector_int_t current_component, previous_component;
171
+ igraph_vector_int_t * current_hood_p = ¤t_hood;
172
+ igraph_vector_int_t * previous_hood_p = &previous_hood;
173
+ igraph_vector_int_t * current_component_p = ¤t_component;
174
+ igraph_vector_int_t * previous_component_p = &previous_component;
175
+ igraph_vector_int_t tmp;
176
+
177
+ if (timeout < 0 )
178
+ {
179
+ IGRAPH_ERROR (" Negative timeout" , IGRAPH_EINVAL);
180
+ }
181
+
182
+ added = IGRAPH_CALLOC (no_of_nodes, igraph_bool_t );
183
+ IGRAPH_CHECK_OOM (added, " Cannot calculate neighborhood size." );
184
+ IGRAPH_FINALLY (igraph_free, added);
185
+
186
+ IGRAPH_VECTOR_INT_INIT_FINALLY (current_hood_p, 0 );
187
+ IGRAPH_VECTOR_INT_INIT_FINALLY (previous_hood_p, 0 );
188
+ IGRAPH_VECTOR_INT_INIT_FINALLY (current_component_p, 0 );
189
+ IGRAPH_VECTOR_INT_INIT_FINALLY (previous_component_p, 0 );
190
+ IGRAPH_VECTOR_INT_INIT_FINALLY (&tmp, 0 );
191
+
192
+ IGRAPH_CHECK (igraph_vector_int_init (in_set, 0 ));
193
+ IGRAPH_CHECK (igraph_vector_int_init (out_set, 0 ));
194
+ igraph_vector_int_clear (in_set);
195
+ igraph_vector_int_clear (out_set);
196
+
197
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_hood_p, node));
198
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_component_p, node));
199
+
200
+ igraph_integer_t previous_size, current_size;
201
+
202
+ for (i = 0 ; i < timeout; i++)
203
+ {
204
+ previous_size = igraph_vector_int_size (previous_component_p);
205
+ current_size = igraph_vector_int_size (current_component_p);
206
+ u32 current_hood_size = igraph_vector_int_size (current_hood_p);
207
+
208
+ if (previous_size < current_size || current_size == 1 )
209
+ {
210
+ // move current objects to previous
211
+ IGRAPH_CHECK (igraph_vector_int_swap (previous_hood_p, current_hood_p));
212
+ IGRAPH_CHECK (igraph_vector_int_swap (previous_component_p, current_component_p));
213
+ igraph_vector_int_clear (current_hood_p);
214
+ igraph_vector_int_clear (current_component_p);
215
+
216
+ // clear flags of added vertices
217
+ memset (added, false , no_of_nodes * sizeof (igraph_bool_t ));
218
+
219
+ std::set<u32 > cache_key;
220
+ for (j = 0 ; j < current_hood_size; j++)
221
+ {
222
+ igraph_integer_t actnode = VECTOR (*previous_hood_p)[j];
223
+ igraph_vector_int_clear (&tmp);
224
+ IGRAPH_CHECK (igraph_neighbors (graph, &tmp, actnode, IGRAPH_OUT));
225
+
226
+ for (k = 0 ; k < igraph_vector_int_size (&tmp); k++)
227
+ {
228
+ igraph_integer_t nei = VECTOR (tmp)[k];
229
+ if (!added[nei])
230
+ {
231
+ added[nei] = true ;
232
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_hood_p, nei));
233
+ cache_key.insert (nei);
234
+ }
235
+ }
236
+ }
237
+
238
+ if (k == 0 )
239
+ {
240
+ continue ;
241
+ }
242
+
243
+ if (const auto cache_it = cache.find (cache_key); cache_it != cache.end ())
244
+ {
245
+ IGRAPH_CHECK (igraph_vector_int_update (current_component_p, cache_it->second ));
246
+ }
247
+ else
248
+ {
249
+ igraph_t subgraph;
250
+ igraph_vs_t subgraph_vertices = igraph_vss_vector (current_hood_p);
251
+ IGRAPH_FINALLY (igraph_vs_destroy, &subgraph_vertices);
252
+ igraph_vector_int_t vertex_map;
253
+ IGRAPH_VECTOR_INT_INIT_FINALLY (&vertex_map, igraph_vector_int_size (current_hood_p));
254
+ IGRAPH_CHECK (igraph_induced_subgraph_map (graph, &subgraph, subgraph_vertices, IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH, nullptr , &vertex_map));
255
+ IGRAPH_FINALLY (igraph_destroy, &subgraph);
256
+
257
+ igraph_vector_int_t membership, csize;
258
+ IGRAPH_VECTOR_INT_INIT_FINALLY (&membership, 0 );
259
+ IGRAPH_VECTOR_INT_INIT_FINALLY (&csize, 0 );
260
+ IGRAPH_CHECK (igraph_connected_components (&subgraph, &membership, &csize, nullptr , IGRAPH_STRONG));
261
+
262
+ u32 max_id = igraph_vector_int_which_max (&csize);
263
+ u32 num_subgraph_vertices = igraph_vcount (&subgraph);
264
+ for (i32 i = 0 ; i < num_subgraph_vertices; i++)
265
+ {
266
+ u32 cid = VECTOR (membership)[i];
267
+ if (cid == max_id)
268
+ {
269
+ IGRAPH_CHECK (igraph_vector_int_push_back (current_component_p, VECTOR (vertex_map)[i]));
270
+ }
271
+ }
272
+
273
+ igraph_vs_destroy (&subgraph_vertices);
274
+ igraph_vector_int_destroy (&vertex_map);
275
+ igraph_vector_int_destroy (&membership);
276
+ igraph_vector_int_destroy (&csize);
277
+ igraph_destroy (&subgraph);
278
+ IGRAPH_FINALLY_CLEAN (5 );
279
+
280
+ igraph_vector_int_t * cache_tmp = new igraph_vector_int_t ;
281
+ IGRAPH_CHECK (igraph_vector_int_init (cache_tmp, 0 )); // cleanup handled by caller
282
+ IGRAPH_CHECK (igraph_vector_int_update (cache_tmp, current_component_p));
283
+ cache[cache_key] = cache_tmp;
284
+ }
285
+ }
286
+ else
287
+ {
288
+ if (previous_size == current_size)
289
+ {
290
+ IGRAPH_CHECK (igraph_vector_int_update (in_set, previous_component_p));
291
+ IGRAPH_CHECK (igraph_vector_int_update (out_set, current_component_p));
292
+ }
293
+
294
+ break ;
295
+ }
296
+ }
297
+
298
+ igraph_vector_int_destroy (current_hood_p);
299
+ igraph_vector_int_destroy (previous_hood_p);
300
+ igraph_vector_int_destroy (current_component_p);
301
+ igraph_vector_int_destroy (previous_component_p);
302
+ igraph_vector_int_destroy (&tmp);
303
+ IGRAPH_FREE (added);
304
+ IGRAPH_FINALLY_CLEAN (6 );
305
+
306
+ return IGRAPH_SUCCESS;
307
+ }
158
308
} // namespace
159
309
160
310
Result<std::vector<Candidate>> detect_candidates (Netlist* nl, const std::vector<DetectionConfiguration>& configs, u32 min_state_size, const std::vector<Gate*>& start_ffs)
@@ -199,7 +349,7 @@ namespace hal
199
349
}
200
350
auto base_graph = res.get ();
201
351
202
- const auto start_vertices_res = base_graph->get_vertices_from_gates (start_gates);
352
+ const auto start_vertices_res = base_graph->get_vertices_from_gates (start_ffs. empty () ? start_gates : start_ffs );
203
353
if (start_vertices_res.is_error ())
204
354
{
205
355
return ERR (start_vertices_res.get_error ());
@@ -358,35 +508,85 @@ namespace hal
358
508
}
359
509
360
510
std::set<GraphCandidate> graph_candidates;
361
- for (const auto v : start_vertices)
362
- {
363
- igraph_vector_int_clear (&in_set);
364
- igraph_vector_int_clear (&out_set);
365
511
366
- if (const auto res = get_saturating_neighborhoods (tmp_graph->get_graph (), &in_set, &out_set, v, config.timeout ); res != IGRAPH_SUCCESS)
512
+ if (config.components == DetectionConfiguration::Components::NONE)
513
+ {
514
+ for (const auto v : start_vertices)
367
515
{
368
- igraph_vector_int_destroy (&in_set);
369
- igraph_vector_int_destroy (&out_set);
370
- return ERR (igraph_strerror (res));
371
- }
516
+ igraph_vector_int_clear (&in_set);
517
+ igraph_vector_int_clear (&out_set);
372
518
373
- u32 size = igraph_vector_int_size (&out_set);
374
- if (size < config.min_register_size )
375
- {
376
- continue ;
519
+ if (const auto res = get_saturating_neighborhoods (tmp_graph->get_graph (), &in_set, &out_set, v, config.timeout ); res != IGRAPH_SUCCESS)
520
+ {
521
+ igraph_vector_int_destroy (&in_set);
522
+ igraph_vector_int_destroy (&out_set);
523
+ return ERR (igraph_strerror (res));
524
+ }
525
+
526
+ u32 size = igraph_vector_int_size (&out_set);
527
+ if (size < config.min_register_size )
528
+ {
529
+ continue ;
530
+ }
531
+
532
+ GraphCandidate c;
533
+ c.size = size;
534
+ for (u32 i = 0 ; i < igraph_vector_int_size (&in_set); i++)
535
+ {
536
+ c.in_reg .insert (VECTOR (in_set)[i]);
537
+ }
538
+ for (u32 i = 0 ; i < igraph_vector_int_size (&out_set); i++)
539
+ {
540
+ c.out_reg .insert (VECTOR (out_set)[i]);
541
+ }
542
+ graph_candidates.insert (c);
377
543
}
544
+ }
545
+ else if (config.components == DetectionConfiguration::Components::CHECK_SCC)
546
+ {
547
+ std::map<std::set<u32 >, igraph_vector_int_t *> scc_cache;
378
548
379
- GraphCandidate c;
380
- c.size = size;
381
- for (u32 i = 0 ; i < igraph_vector_int_size (&in_set); i++)
549
+ for (const auto v : start_vertices)
382
550
{
383
- c.in_reg .insert (VECTOR (in_set)[i]);
551
+ igraph_vector_int_clear (&in_set);
552
+ igraph_vector_int_clear (&out_set);
553
+
554
+ if (const auto res = get_saturating_neighborhoods_scc (tmp_graph->get_graph (), &in_set, &out_set, v, config.timeout , scc_cache); res != IGRAPH_SUCCESS)
555
+ {
556
+ igraph_vector_int_destroy (&in_set);
557
+ igraph_vector_int_destroy (&out_set);
558
+ for (auto & [_, comp] : scc_cache)
559
+ {
560
+ igraph_vector_int_destroy (comp);
561
+ delete comp;
562
+ }
563
+ return ERR (igraph_strerror (res));
564
+ }
565
+
566
+ u32 size = igraph_vector_int_size (&out_set);
567
+ if (size < config.min_register_size )
568
+ {
569
+ continue ;
570
+ }
571
+
572
+ GraphCandidate c;
573
+ c.size = size;
574
+ for (u32 i = 0 ; i < igraph_vector_int_size (&in_set); i++)
575
+ {
576
+ c.in_reg .insert (VECTOR (in_set)[i]);
577
+ }
578
+ for (u32 i = 0 ; i < igraph_vector_int_size (&out_set); i++)
579
+ {
580
+ c.out_reg .insert (VECTOR (out_set)[i]);
581
+ }
582
+ graph_candidates.insert (c);
384
583
}
385
- for (u32 i = 0 ; i < igraph_vector_int_size (&out_set); i++)
584
+
585
+ for (auto & [_, comp] : scc_cache)
386
586
{
387
- c.out_reg .insert (VECTOR (out_set)[i]);
587
+ igraph_vector_int_destroy (comp);
588
+ delete comp;
388
589
}
389
- graph_candidates.insert (c);
390
590
}
391
591
392
592
igraph_vector_int_destroy (&in_set);
@@ -426,8 +626,6 @@ namespace hal
426
626
427
627
duration_in_seconds = std::chrono::duration<double >(std::chrono::system_clock::now () - start_inner).count ();
428
628
log_info (" hawkeye" , " successfully completed neighborhood discovery in {} seconds" , duration_in_seconds);
429
-
430
- // TODO implement SCC method
431
629
}
432
630
433
631
duration_in_seconds = std::chrono::duration<double >(std::chrono::system_clock::now () - start).count ();
0 commit comments