Merge lp:~nicholas-dahm/igraph/compat-fn into lp:~igraph/igraph/0.6-main-old
- compat-fn
- Merge into 0.6-main-old
Status: | Merged |
---|---|
Merged at revision: | 2762 |
Proposed branch: | lp:~nicholas-dahm/igraph/compat-fn |
Merge into: | lp:~igraph/igraph/0.6-main-old |
Diff against target: |
818 lines (+297/-58) 5 files modified
examples/simple/igraph_isomorphic_vf2.c (+15/-15) examples/simple/igraph_lcf.c (+1/-1) include/igraph_topology.h (+60/-12) interfaces/R/src/config.h.in (+3/-0) src/topology.c (+218/-30) |
To merge this branch: | bzr merge lp:~nicholas-dahm/igraph/compat-fn |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gábor Csárdi | Approve | ||
Nicholas Dahm (community) | Needs Fixing | ||
Review via email: mp+100732@code.launchpad.net |
Commit message
Description of the change
Added functionality to use custom node and edge checking functions when performing (sub)isomorphism operations using the VF2 algorithm.
Nicholas Dahm (nicholas-dahm) wrote : | # |
Gábor Csárdi (gabor.csardi) wrote : | # |
Thanks Nick, this looks very nice. The only thing I would like to change is the handling of extra argument(s). For other igraph functions with callbacks this is just a void* and then it is up to the callback to do whatever it wants with it. So I think it would be better to have the same here.
Could you please check that 'make check' is clean. Maybe there are no tests at all for the VF2 functions, so nothing can go wrong here....
Thanks again!
Gábor Csárdi (gabor.csardi) wrote : | # |
Btw. if you don't want to change the extra argument, I can do that, too. If you can do it, that is even better. :)
Nicholas Dahm (nicholas-dahm) wrote : | # |
Gabor. I'm not sure you got my emails regarding this, but a decision needs to be made regarding the extra argument. The reason is that we are passing in [up to] 3 functions now, so technically there would be 3 arguments. This is why, after consulting with Tamas, I packaged the 3 args into a struct for ease of use. If you prefer to have 3 separate args, or want me to pack each function with an arg or anything like this, just let me know and I'll do it.
I'm going to propose this again, just so that you definitely get this message. Please don't take this as impatience on my part :)
Gábor Csárdi (gabor.csardi) wrote : | # |
I think it is simpler to have just _one_ void* arg, and this is passed to all three functions. Then in the callback you can cast it to whatever you like, even a struct with three members if that's what you like. It is largely a matter of taste, but this is how it was done in other igraph functions.
Another small comment. Please try to avoid commit messages like 'misc', these are not very helpful. If it is really 'misc', then you might split it to multiple commits. You can use the 'bzr shelve' command to temporarily shelve part(s) of the modifications of the file, and then 'bzr unshelve' to get it back.
Anyway, I'll merge this today or tomorrow, and will change the extra argument.
Thanks again for the code!
Gábor Csárdi (gabor.csardi) wrote : | # |
Btw. make check fails for some test cases.
Nicholas Dahm (nicholas-dahm) wrote : | # |
The problem with using one void* arg and passing that to all callback functions is that some isomorphism functions have more callback functions than others, so the callback function can't know how many args are packed and which one they can use. I think it would be better to let the isomorphism functions take a void* arg which is then casted to a void** arg and then passes the correct arg[x] (where arg[x] is type void*) to the callback. This would also help keep the callback functions simple. This is what I came up with while consulting to Tamas, and he suggested to change it to the struct for readability. I'm happy to switch it back to void*'s if you prefer, just let me know.
Apologies about the misc commits. These were generally from when I save my work from one PC when going to another. I will try to make better comments for these in future.
Nicholas Dahm (nicholas-dahm) wrote : | # |
Yes sorry I had forgotten about make check. I will check and fix these now.
Gábor Csárdi (gabor.csardi) wrote : | # |
You can leave the struct for the extra argument, I'll see what I'll do with it.
Fixing 'make check' is not big deal, just need to update the function calls that have a new signature.
- 2642. By Nicholas Dahm
-
fixed make checks for vf2
Nicholas Dahm (nicholas-dahm) wrote : | # |
I fixed the make checks regarding vf2. There are still 2 failing checks regarding scg, but I can't see how they are related or understand what's wrong with these.
Gábor Csárdi (gabor.csardi) wrote : | # |
The SCG checks are unrelated. Thanks!
Gábor Csárdi (gabor.csardi) wrote : | # |
I have merged this in revision #2762 (0.6-main).
Gábor Csárdi (gabor.csardi) wrote : | # |
Three more comments.
1 I eliminated the struct for the extra arguments, it is just a void* now everywhere.
2 It is useful to write a test case for a new functionality, see #2762.
3 From the test case it turns out quickly, that the edge-compatibility functions were never called, I have fixed this.
Thanks again for your code!
Nicholas Dahm (nicholas-dahm) wrote : | # |
Thanks for doing that, I will write test cases in future :)
Preview Diff
1 | === modified file 'examples/simple/igraph_isomorphic_vf2.c' |
2 | --- examples/simple/igraph_isomorphic_vf2.c 2012-05-20 02:19:29 +0000 |
3 | +++ examples/simple/igraph_isomorphic_vf2.c 2012-05-23 04:31:20 +0000 |
4 | @@ -61,7 +61,7 @@ |
5 | } |
6 | |
7 | /* Without colors, number of isomorphisms */ |
8 | - igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, 0, 0, &count); |
9 | + igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, 0, 0, &count, 0, 0, 0); |
10 | if (count != 200) { |
11 | fprintf(stderr, "Count without colors failed, expected %li, got %li.\n", |
12 | (long int) 200, (long int) count); |
13 | @@ -71,7 +71,7 @@ |
14 | /* Everything has the same colors */ |
15 | igraph_vector_int_init(&color1, igraph_vcount(&ring1)); |
16 | igraph_vector_int_init(&color2, igraph_vcount(&ring2)); |
17 | - igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0); |
18 | + igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0, 0, 0, 0); |
19 | if (!iso) { |
20 | fprintf(stderr, "Single color failed.\n"); |
21 | return 3; |
22 | @@ -82,7 +82,7 @@ |
23 | VECTOR(color1)[i] = VECTOR(color2)[i] = 0; |
24 | VECTOR(color1)[i+1] = VECTOR(color2)[i] = 1; |
25 | } |
26 | - igraph_count_isomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &count); |
27 | + igraph_count_isomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &count, 0, 0, 0); |
28 | if (count != 100) { |
29 | fprintf(stderr, "Count with two colors failed, expected %li, got %li.\n", |
30 | (long int) 100, (long int) count); |
31 | @@ -93,7 +93,7 @@ |
32 | for (i=0; i<igraph_vector_int_size(&color1); i++) { |
33 | VECTOR(color1)[i] = VECTOR(color2)[i] = i; |
34 | } |
35 | - igraph_count_isomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &count); |
36 | + igraph_count_isomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &count, 0, 0, 0); |
37 | if (count != 1) { |
38 | fprintf(stderr, "Count with separate colors failed, expected %li, got %li.\n", |
39 | (long int) 1, (long int) count); |
40 | @@ -104,7 +104,7 @@ |
41 | igraph_vector_int_fill(&color1, 0); |
42 | igraph_vector_int_fill(&color2, 0); |
43 | VECTOR(color1)[0]=1; |
44 | - igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0); |
45 | + igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0, 0, 0, 0); |
46 | if (iso) { |
47 | fprintf(stderr, "Negative test failed.\n"); |
48 | return 6; |
49 | @@ -115,7 +115,7 @@ |
50 | igraph_vector_int_fill(&color2, 0); |
51 | VECTOR(color1)[0]=1; VECTOR(color1)[1]=1; |
52 | VECTOR(color2)[0]=1; VECTOR(color2)[2]=1; |
53 | - igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0); |
54 | + igraph_isomorphic_vf2(&ring1, &ring2, &color1, &color2, 0, 0, &iso, 0, 0, 0, 0, 0); |
55 | if (iso) { |
56 | fprintf(stderr, "Second negative test failed.\n"); |
57 | return 7; |
58 | @@ -139,7 +139,7 @@ |
59 | igraph_vector_int_init(&color1, igraph_vcount(&ring1)); |
60 | igraph_vector_int_init(&color2, igraph_vcount(&ring2)); |
61 | igraph_count_subisomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, |
62 | - &count); |
63 | + &count, 0, 0, 0); |
64 | if (count != 42) { |
65 | fprintf(stderr, "Count with one color failed, expected %li, got %li.\n", |
66 | (long int) 42, (long int) count); |
67 | @@ -156,7 +156,7 @@ |
68 | VECTOR(color2)[i+1] = 1; |
69 | } |
70 | igraph_count_subisomorphisms_vf2(&ring1, &ring2, &color1, &color2, 0, 0, |
71 | - &count); |
72 | + &count, 0, 0, 0); |
73 | if (count != 21) { |
74 | fprintf(stderr, "Count with two colors failed, expected %li, got %li.\n", |
75 | (long int) 21, (long int) count); |
76 | @@ -182,7 +182,7 @@ |
77 | /* Everything has the same color */ |
78 | igraph_vector_int_init(&color1, igraph_ecount(&ring1)); |
79 | igraph_vector_int_init(&color2, igraph_ecount(&ring2)); |
80 | - igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0); |
81 | + igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0, 0, 0, 0); |
82 | if (!iso) { |
83 | fprintf(stderr, "Single edge-color failed.\n"); |
84 | return 41; |
85 | @@ -193,7 +193,7 @@ |
86 | VECTOR(color1)[i] = VECTOR(color2)[i] = 0; |
87 | VECTOR(color1)[i+1] = VECTOR(color2)[i] = 1; |
88 | } |
89 | - igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &count); |
90 | + igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &count, 0, 0, 0); |
91 | if (count != 100) { |
92 | fprintf(stderr, "Count with two edge colors failed, expected %li, got %li.\n", |
93 | (long int) 100, (long int) count); |
94 | @@ -204,7 +204,7 @@ |
95 | for (i=0; i<igraph_vector_int_size(&color1); i++) { |
96 | VECTOR(color1)[i] = VECTOR(color2)[i] = i; |
97 | } |
98 | - igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &count); |
99 | + igraph_count_isomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &count, 0, 0, 0); |
100 | if (count != 1) { |
101 | fprintf(stderr, "Count with separate edge colors failed, expected %li, got %li.\n", |
102 | (long int) 1, (long int) count); |
103 | @@ -215,7 +215,7 @@ |
104 | igraph_vector_int_fill(&color1, 0); |
105 | igraph_vector_int_fill(&color2, 0); |
106 | VECTOR(color1)[0]=1; |
107 | - igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0); |
108 | + igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0, 0, 0, 0); |
109 | if (iso) { |
110 | fprintf(stderr, "Negative edge test failed.\n"); |
111 | return 44; |
112 | @@ -226,7 +226,7 @@ |
113 | igraph_vector_int_fill(&color2, 0); |
114 | VECTOR(color1)[0]=1; VECTOR(color1)[1]=1; |
115 | VECTOR(color2)[0]=1; VECTOR(color2)[2]=1; |
116 | - igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0); |
117 | + igraph_isomorphic_vf2(&ring1, &ring2, 0, 0, &color1, &color2, &iso, 0, 0, 0, 0, 0); |
118 | if (iso) { |
119 | fprintf(stderr, "Second negative edge test failed.\n"); |
120 | return 45; |
121 | @@ -249,7 +249,7 @@ |
122 | igraph_vector_int_init(&color1, igraph_ecount(&ring1)); |
123 | igraph_vector_int_init(&color2, igraph_ecount(&ring2)); |
124 | igraph_count_subisomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, |
125 | - &count); |
126 | + &count, 0, 0, 0); |
127 | if (count != 42) { |
128 | fprintf(stderr, "Count with one edge color failed, expected %li, got %li.\n", |
129 | (long int) 42, (long int) count); |
130 | @@ -266,7 +266,7 @@ |
131 | VECTOR(color2)[i+1] = 1; |
132 | } |
133 | igraph_count_subisomorphisms_vf2(&ring1, &ring2, 0, 0, &color1, &color2, |
134 | - &count); |
135 | + &count, 0, 0, 0); |
136 | if (count != 22) { |
137 | fprintf(stderr, "Count with two edge colors failed, expected %li, got %li.\n", |
138 | (long int) 22, (long int) count); |
139 | |
140 | === modified file 'examples/simple/igraph_lcf.c' |
141 | --- examples/simple/igraph_lcf.c 2012-05-20 02:19:29 +0000 |
142 | +++ examples/simple/igraph_lcf.c 2012-05-23 04:31:20 +0000 |
143 | @@ -34,7 +34,7 @@ |
144 | igraph_isomorphic_vf2(&g, &g2, |
145 | /*vertex.color1=*/ 0, /*vertex.color2=*/ 0, |
146 | /*edge.color1=*/ 0, /*edge.color2=*/ 0, |
147 | - &iso, 0, 0); |
148 | + &iso, 0, 0, 0, 0, 0); |
149 | if (!iso) { |
150 | printf("OOOPS!\n"); |
151 | return 1; |
152 | |
153 | === modified file 'include/igraph_topology.h' |
154 | --- include/igraph_topology.h 2012-05-20 02:19:29 +0000 |
155 | +++ include/igraph_topology.h 2012-05-23 04:31:20 +0000 |
156 | @@ -73,45 +73,85 @@ |
157 | * igraph_isomorphic_function_vf2() when it was called. |
158 | * \return Boolean, whether to continue with the isomorphism search. |
159 | */ |
160 | + |
161 | + |
162 | typedef igraph_bool_t igraph_isohandler_t(const igraph_vector_t *map12, |
163 | const igraph_vector_t *map21, void *arg); |
164 | |
165 | +typedef igraph_bool_t igraph_isocompat_t(const igraph_t *graph1, |
166 | + const igraph_t *graph2, |
167 | + const igraph_integer_t g1_num, |
168 | + const igraph_integer_t g2_num, |
169 | + void *arg); |
170 | + |
171 | +/** |
172 | + * \struct igraph_isomorphic_function_vf2_args_t |
173 | + * Information about a BLISS run |
174 | + * Parameter bundle to be used for different subfunctions of vf2 algorithms. |
175 | + * |
176 | + * \member isohandler_fn_arg Argument passed through to isohandler_fn |
177 | + * \member node_compat_fn_arg Argument passed through to node_compat_fn |
178 | + * \member edge_compat_fn_arg Argument passed through to edge_compat_fn |
179 | + */ |
180 | + |
181 | +typedef struct{ |
182 | + void *isohandler_fn_arg; |
183 | + void *node_compat_fn_arg; |
184 | + void *edge_compat_fn_arg; |
185 | +} igraph_isomorphic_function_vf2_args_t; |
186 | + |
187 | int igraph_isomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2, |
188 | const igraph_vector_int_t *vertex_color1, |
189 | const igraph_vector_int_t *vertex_color2, |
190 | const igraph_vector_int_t *edge_color1, |
191 | const igraph_vector_int_t *edge_color2, |
192 | - igraph_bool_t *iso, igraph_vector_t *map12, |
193 | - igraph_vector_t *map21); |
194 | + igraph_bool_t *iso, |
195 | + igraph_vector_t *map12, |
196 | + igraph_vector_t *map21, |
197 | + igraph_isocompat_t *node_compat_fn, |
198 | + igraph_isocompat_t *edge_compat_fn, |
199 | + igraph_isomorphic_function_vf2_args_t *args); |
200 | int igraph_isomorphic_function_vf2(const igraph_t *graph1, const igraph_t *graph2, |
201 | const igraph_vector_int_t *vertex_color1, |
202 | const igraph_vector_int_t *vertex_color2, |
203 | const igraph_vector_int_t *edge_color1, |
204 | const igraph_vector_int_t *edge_color2, |
205 | igraph_vector_t *map12, igraph_vector_t *map21, |
206 | - igraph_isohandler_t *function, |
207 | - void *arg); |
208 | + igraph_isohandler_t *isohandler_fn, |
209 | + igraph_isocompat_t *node_compat_fn, |
210 | + igraph_isocompat_t *edge_compat_fn, |
211 | + igraph_isomorphic_function_vf2_args_t *args); |
212 | int igraph_count_isomorphisms_vf2(const igraph_t *graph1, const igraph_t *graph2, |
213 | const igraph_vector_int_t *vertex_color1, |
214 | const igraph_vector_int_t *vertex_color2, |
215 | const igraph_vector_int_t *edge_color1, |
216 | const igraph_vector_int_t *edge_color2, |
217 | - igraph_integer_t *count); |
218 | + igraph_integer_t *count, |
219 | + igraph_isocompat_t *node_compat_fn, |
220 | + igraph_isocompat_t *edge_compat_fn, |
221 | + igraph_isomorphic_function_vf2_args_t *args); |
222 | int igraph_get_isomorphisms_vf2(const igraph_t *graph1, |
223 | const igraph_t *graph2, |
224 | const igraph_vector_int_t *vertex_color1, |
225 | const igraph_vector_int_t *vertex_color2, |
226 | const igraph_vector_int_t *edge_color1, |
227 | const igraph_vector_int_t *edge_color2, |
228 | - igraph_vector_ptr_t *maps); |
229 | + igraph_vector_ptr_t *maps, |
230 | + igraph_isocompat_t *node_compat_fn, |
231 | + igraph_isocompat_t *edge_compat_fn, |
232 | + igraph_isomorphic_function_vf2_args_t *args); |
233 | |
234 | int igraph_subisomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2, |
235 | const igraph_vector_int_t *vertex_color1, |
236 | const igraph_vector_int_t *vertex_color2, |
237 | const igraph_vector_int_t *edge_color1, |
238 | const igraph_vector_int_t *edge_color2, |
239 | - igraph_bool_t *iso, igraph_vector_t *map12, |
240 | - igraph_vector_t *map21); |
241 | + igraph_bool_t *iso, |
242 | + igraph_vector_t *map12, |
243 | + igraph_vector_t *map21, |
244 | + igraph_isocompat_t *node_compat_fn, |
245 | + igraph_isocompat_t *edge_compat_fn, |
246 | + igraph_isomorphic_function_vf2_args_t *args); |
247 | int igraph_subisomorphic_function_vf2(const igraph_t *graph1, |
248 | const igraph_t *graph2, |
249 | const igraph_vector_int_t *vertex_color1, |
250 | @@ -120,21 +160,29 @@ |
251 | const igraph_vector_int_t *edge_color2, |
252 | igraph_vector_t *map12, |
253 | igraph_vector_t *map21, |
254 | - igraph_isohandler_t *function, |
255 | - void *arg); |
256 | + igraph_isohandler_t *isohandler_fn, |
257 | + igraph_isocompat_t *node_compat_fn, |
258 | + igraph_isocompat_t *edge_compat_fn, |
259 | + igraph_isomorphic_function_vf2_args_t *args); |
260 | int igraph_count_subisomorphisms_vf2(const igraph_t *graph1, const igraph_t *graph2, |
261 | const igraph_vector_int_t *vertex_color1, |
262 | const igraph_vector_int_t *vertex_color2, |
263 | const igraph_vector_int_t *edge_color1, |
264 | const igraph_vector_int_t *edge_color2, |
265 | - igraph_integer_t *count); |
266 | + igraph_integer_t *count, |
267 | + igraph_isocompat_t *node_compat_fn, |
268 | + igraph_isocompat_t *edge_compat_fn, |
269 | + igraph_isomorphic_function_vf2_args_t *args); |
270 | int igraph_get_subisomorphisms_vf2(const igraph_t *graph1, |
271 | const igraph_t *graph2, |
272 | const igraph_vector_int_t *vertex_color1, |
273 | const igraph_vector_int_t *vertex_color2, |
274 | const igraph_vector_int_t *edge_color1, |
275 | const igraph_vector_int_t *edge_color2, |
276 | - igraph_vector_ptr_t *maps); |
277 | + igraph_vector_ptr_t *maps, |
278 | + igraph_isocompat_t *node_compat_fn, |
279 | + igraph_isocompat_t *edge_compat_fn, |
280 | + igraph_isomorphic_function_vf2_args_t *args); |
281 | |
282 | /* BLISS family */ |
283 | /** |
284 | |
285 | === modified file 'interfaces/R/src/config.h.in' |
286 | --- interfaces/R/src/config.h.in 2012-02-21 02:43:45 +0000 |
287 | +++ interfaces/R/src/config.h.in 2012-05-23 04:31:20 +0000 |
288 | @@ -84,6 +84,9 @@ |
289 | /* Define to the one symbol short name of this package. */ |
290 | #undef PACKAGE_TARNAME |
291 | |
292 | +/* Define to the home page for this package. */ |
293 | +#undef PACKAGE_URL |
294 | + |
295 | /* Define to the version of this package. */ |
296 | #undef PACKAGE_VERSION |
297 | |
298 | |
299 | === modified file 'src/topology.c' |
300 | --- src/topology.c 2012-05-20 02:19:29 +0000 |
301 | +++ src/topology.c 2012-05-23 04:31:20 +0000 |
302 | @@ -794,7 +794,7 @@ |
303 | } else if (nodes1==3 || nodes1==4) { |
304 | igraph_isomorphic_34(graph1, graph2, iso); |
305 | } else if (dir1) { |
306 | - igraph_isomorphic_vf2(graph1, graph2, 0, 0, 0, 0, iso, 0, 0); |
307 | + igraph_isomorphic_vf2(graph1, graph2, 0, 0, 0, 0, iso, 0, 0, 0, 0, 0); |
308 | } else { |
309 | igraph_isomorphic_bliss(graph1, graph2, iso, 0, 0, /*sh1=*/0, /*sh2=*/0, 0, 0); |
310 | } |
311 | @@ -1042,11 +1042,17 @@ |
312 | * graphs are not isomorphic then a zero-length vector is returned. |
313 | * \param map21 This is the same as \p map12, but for the permutation |
314 | * taking \p graph2 to \p graph1. |
315 | - * \param function The callback function to be called if an |
316 | + * \param isohandler_fn The callback function to be called if an |
317 | * isomorphism is found. See also \ref igraph_isohandler_t. |
318 | - * \param arg An extra argument to pass to \p function. E.g. if \p |
319 | - * function needs to store the isomorphisms found, then \p arg may |
320 | - * point to a container for them. |
321 | + * \param node_compat_fn A pointer to a function of type \ref |
322 | + * igraph_isocompat_t. This function will be called by the algorithm to |
323 | + * determine whether two nodes are compatible. |
324 | + * \param edge_compat_fn A pointer to a function of type \ref |
325 | + * igraph_isocompat_t. This function will be called by the algorithm to |
326 | + * determine whether two edges are compatible. |
327 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
328 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
329 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
330 | * \return Error code. |
331 | * |
332 | * Time complexity: exponential. |
333 | @@ -1059,8 +1065,10 @@ |
334 | const igraph_vector_int_t *edge_color2, |
335 | igraph_vector_t *map12, |
336 | igraph_vector_t *map21, |
337 | - igraph_isohandler_t *function, |
338 | - void *arg) { |
339 | + igraph_isohandler_t *isohandler_fn, |
340 | + igraph_isocompat_t *node_compat_fn, |
341 | + igraph_isocompat_t *edge_compat_fn, |
342 | + igraph_isomorphic_function_vf2_args_t *args) { |
343 | |
344 | long int no_of_nodes=igraph_vcount(graph1); |
345 | long int no_of_edges=igraph_ecount(graph1); |
346 | @@ -1075,6 +1083,14 @@ |
347 | igraph_stack_t path; |
348 | igraph_lazy_adjlist_t inadj1, inadj2, outadj1, outadj2; |
349 | igraph_vector_t indeg1, indeg2, outdeg1, outdeg2; |
350 | + void *isohandler_fn_arg = 0; |
351 | + void *node_compat_fn_arg = 0; |
352 | + void *edge_compat_fn_arg = 0; |
353 | + if (args) { |
354 | + isohandler_fn_arg = args->isohandler_fn_arg; |
355 | + node_compat_fn_arg = args->node_compat_fn_arg; |
356 | + edge_compat_fn_arg = args->edge_compat_fn_arg; |
357 | + } |
358 | |
359 | if (igraph_is_directed(graph1) != igraph_is_directed(graph2)) { |
360 | IGRAPH_ERROR("Cannot compare directed and undirected graphs", |
361 | @@ -1347,6 +1363,9 @@ |
362 | if (vertex_color1 && VECTOR(*vertex_color1)[cand1] != VECTOR(*vertex_color2)[cand2]) { |
363 | end=1; |
364 | } |
365 | + if (node_compat_fn && !node_compat_fn(graph1, graph2, cand1, cand2, node_compat_fn_arg)) { |
366 | + end=1; |
367 | + } |
368 | |
369 | for (i=0; !end && i<igraph_vector_size(inneis_1); i++) { |
370 | long int node=VECTOR(*inneis_1)[i]; |
371 | @@ -1365,6 +1384,9 @@ |
372 | VECTOR(*edge_color2)[(long int)eid2]) { |
373 | end=1; |
374 | } |
375 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
376 | + end=1; |
377 | + } |
378 | } |
379 | } else { |
380 | if (VECTOR(in_1)[node] != 0) { |
381 | @@ -1392,6 +1414,9 @@ |
382 | VECTOR(*edge_color2)[(long int)eid2]) { |
383 | end=1; |
384 | } |
385 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
386 | + end=1; |
387 | + } |
388 | } |
389 | } else { |
390 | if (VECTOR(in_1)[node] != 0) { |
391 | @@ -1419,6 +1444,9 @@ |
392 | VECTOR(*edge_color2)[(long int)eid2]) { |
393 | end=1; |
394 | } |
395 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
396 | + end=1; |
397 | + } |
398 | } |
399 | } else { |
400 | if (VECTOR(in_2)[node] != 0) { |
401 | @@ -1446,6 +1474,9 @@ |
402 | VECTOR(*edge_color2)[(long int)eid2]) { |
403 | end=1; |
404 | } |
405 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
406 | + end=1; |
407 | + } |
408 | } |
409 | } else { |
410 | if (VECTOR(in_2)[node] != 0) { |
411 | @@ -1520,8 +1551,8 @@ |
412 | |
413 | } |
414 | |
415 | - if (matched_nodes==no_of_nodes && function) { |
416 | - if (!function(core_1, core_2, arg)) { |
417 | + if (matched_nodes==no_of_nodes && isohandler_fn) { |
418 | + if (!isohandler_fn(core_1, core_2, isohandler_fn_arg)) { |
419 | break; |
420 | } |
421 | } |
422 | @@ -1600,6 +1631,15 @@ |
423 | * a NULL pointer then the mapping from \p graph2 to \p graph1 is |
424 | * stored here. If the graphs are not isomorphic then the vector is |
425 | * cleared (ie. has zero elements). |
426 | + * \param node_compat_fn A pointer to a function of type \ref |
427 | + * igraph_isocompat_t. This function will be called by the algorithm to |
428 | + * determine whether two nodes are compatible. |
429 | + * \param edge_compat_fn A pointer to a function of type \ref |
430 | + * igraph_isocompat_t. This function will be called by the algorithm to |
431 | + * determine whether two edges are compatible. |
432 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
433 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
434 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
435 | * \return Error code. |
436 | * |
437 | * \sa \ref igraph_subisomorphic_vf2(), |
438 | @@ -1617,8 +1657,19 @@ |
439 | const igraph_vector_int_t *edge_color1, |
440 | const igraph_vector_int_t *edge_color2, |
441 | igraph_bool_t *iso, igraph_vector_t *map12, |
442 | - igraph_vector_t *map21) { |
443 | + igraph_vector_t *map21, |
444 | + igraph_isocompat_t *node_compat_fn, |
445 | + igraph_isocompat_t *edge_compat_fn, |
446 | + igraph_isomorphic_function_vf2_args_t *args) { |
447 | |
448 | + igraph_isomorphic_function_vf2_args_t newargs; |
449 | + newargs.isohandler_fn_arg = iso; |
450 | + newargs.node_compat_fn_arg = 0; |
451 | + newargs.edge_compat_fn_arg = 0; |
452 | + if (args) { |
453 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
454 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
455 | + } |
456 | *iso=0; |
457 | IGRAPH_CHECK(igraph_isomorphic_function_vf2(graph1, graph2, |
458 | vertex_color1, vertex_color2, |
459 | @@ -1626,7 +1677,8 @@ |
460 | map12, map21, |
461 | (igraph_isohandler_t*) |
462 | igraph_i_isomorphic_vf2, |
463 | - iso)); |
464 | + node_compat_fn, edge_compat_fn, |
465 | + &newargs)); |
466 | if (! *iso) { |
467 | if (map12) { igraph_vector_clear(map12); } |
468 | if (map21) { igraph_vector_clear(map21); } |
469 | @@ -1664,6 +1716,15 @@ |
470 | * edge-colored. |
471 | * \param edge_color2 The edge color vector for the second graph. |
472 | * \param count Point to an integer, the result will be stored here. |
473 | + * \param node_compat_fn A pointer to a function of type \ref |
474 | + * igraph_isocompat_t. This function will be called by the algorithm to |
475 | + * determine whether two nodes are compatible. |
476 | + * \param edge_compat_fn A pointer to a function of type \ref |
477 | + * igraph_isocompat_t. This function will be called by the algorithm to |
478 | + * determine whether two edges are compatible. |
479 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
480 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
481 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
482 | * \return Error code. |
483 | * |
484 | * Time complexity: exponential. |
485 | @@ -1674,8 +1735,19 @@ |
486 | const igraph_vector_int_t *vertex_color2, |
487 | const igraph_vector_int_t *edge_color1, |
488 | const igraph_vector_int_t *edge_color2, |
489 | - igraph_integer_t *count) { |
490 | + igraph_integer_t *count, |
491 | + igraph_isocompat_t *node_compat_fn, |
492 | + igraph_isocompat_t *edge_compat_fn, |
493 | + igraph_isomorphic_function_vf2_args_t *args) { |
494 | |
495 | + igraph_isomorphic_function_vf2_args_t newargs; |
496 | + newargs.isohandler_fn_arg = count; |
497 | + newargs.node_compat_fn_arg = 0; |
498 | + newargs.edge_compat_fn_arg = 0; |
499 | + if (args) { |
500 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
501 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
502 | + } |
503 | *count=0; |
504 | IGRAPH_CHECK(igraph_isomorphic_function_vf2(graph1, graph2, |
505 | vertex_color1, vertex_color2, |
506 | @@ -1683,7 +1755,8 @@ |
507 | 0, 0, |
508 | (igraph_isohandler_t*) |
509 | igraph_i_count_isomorphisms_vf2, |
510 | - count)); |
511 | + node_compat_fn, edge_compat_fn, |
512 | + &newargs)); |
513 | return 0; |
514 | } |
515 | |
516 | @@ -1747,6 +1820,15 @@ |
517 | * <function>free()</function> and then 3) call \ref |
518 | * igraph_vector_ptr_destroy() on the pointer vector to deallocate all |
519 | * memory when \p maps is no longer needed. |
520 | + * \param node_compat_fn A pointer to a function of type \ref |
521 | + * igraph_isocompat_t. This function will be called by the algorithm to |
522 | + * determine whether two nodes are compatible. |
523 | + * \param edge_compat_fn A pointer to a function of type \ref |
524 | + * igraph_isocompat_t. This function will be called by the algorithm to |
525 | + * determine whether two edges are compatible. |
526 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
527 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
528 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
529 | * \return Error code. |
530 | * |
531 | * Time complexity: exponential. |
532 | @@ -1758,8 +1840,20 @@ |
533 | const igraph_vector_int_t *vertex_color2, |
534 | const igraph_vector_int_t *edge_color1, |
535 | const igraph_vector_int_t *edge_color2, |
536 | - igraph_vector_ptr_t *maps) { |
537 | + igraph_vector_ptr_t *maps, |
538 | + igraph_isocompat_t *node_compat_fn, |
539 | + igraph_isocompat_t *edge_compat_fn, |
540 | + igraph_isomorphic_function_vf2_args_t *args) { |
541 | |
542 | + igraph_isomorphic_function_vf2_args_t newargs; |
543 | + newargs.isohandler_fn_arg = maps; |
544 | + newargs.node_compat_fn_arg = 0; |
545 | + newargs.edge_compat_fn_arg = 0; |
546 | + if (args) { |
547 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
548 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
549 | + } |
550 | + |
551 | igraph_vector_ptr_clear(maps); |
552 | IGRAPH_FINALLY(igraph_i_get_isomorphisms_free, maps); |
553 | IGRAPH_CHECK(igraph_isomorphic_function_vf2(graph1, graph2, |
554 | @@ -1768,7 +1862,8 @@ |
555 | 0, 0, |
556 | (igraph_isohandler_t*) |
557 | igraph_i_get_isomorphisms_vf2, |
558 | - maps)); |
559 | + node_compat_fn, edge_compat_fn, |
560 | + &newargs)); |
561 | IGRAPH_FINALLY_CLEAN(1); |
562 | return 0; |
563 | } |
564 | @@ -1795,7 +1890,7 @@ |
565 | int igraph_subisomorphic(const igraph_t *graph1, const igraph_t *graph2, |
566 | igraph_bool_t *iso) { |
567 | |
568 | - return igraph_subisomorphic_vf2(graph1, graph2, 0, 0, 0, 0, iso, 0, 0); |
569 | + return igraph_subisomorphic_vf2(graph1, graph2, 0, 0, 0, 0, iso, 0, 0, 0, 0, 0); |
570 | } |
571 | |
572 | /** |
573 | @@ -1805,7 +1900,7 @@ |
574 | * This function is the pair of \ref igraph_isomorphic_function_vf2(), |
575 | * for subgraph isomorphism problems. It searches for subgraphs of \p |
576 | * graph1 which are isomorphic to \p graph2. When it founds an |
577 | - * isomorphic mapping it calls the supplied callback \p function. |
578 | + * isomorphic mapping it calls the supplied callback \p isohandler_fn. |
579 | * The mapping (and its inverse) and the additional \p arg argument |
580 | * are supplied to the callback. |
581 | * \param graph1 The first input graph, may be directed or |
582 | @@ -1830,12 +1925,20 @@ |
583 | * \param map21 Pointer to a vector ot \c NULL. If not \c NULL, then |
584 | * an isomorphic mapping from \p graph2 to \p graph1 is stored |
585 | * here. |
586 | - * \param function A pointer to a function of type \ref |
587 | + * \param isohandler_fn A pointer to a function of type \ref |
588 | * igraph_isohandler_t. This will be called whenever a subgraph |
589 | * isomorphism is found. If the function returns with a non-zero value |
590 | * then the search is continued, otherwise it stops and the function |
591 | * returns. |
592 | - * \param arg Extra argument to supply to the callback \p function. |
593 | + * \param node_compat_fn A pointer to a function of type \ref |
594 | + * igraph_isocompat_t. This function will be called by the algorithm to |
595 | + * determine whether two nodes are compatible. |
596 | + * \param edge_compat_fn A pointer to a function of type \ref |
597 | + * igraph_isocompat_t. This function will be called by the algorithm to |
598 | + * determine whether two edges are compatible. |
599 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
600 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
601 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
602 | * \return Error code. |
603 | * |
604 | * Time complexity: exponential. |
605 | @@ -1849,8 +1952,10 @@ |
606 | const igraph_vector_int_t *edge_color2, |
607 | igraph_vector_t *map12, |
608 | igraph_vector_t *map21, |
609 | - igraph_isohandler_t *function, |
610 | - void *arg) { |
611 | + igraph_isohandler_t *isohandler_fn, |
612 | + igraph_isocompat_t *node_compat_fn, |
613 | + igraph_isocompat_t *edge_compat_fn, |
614 | + igraph_isomorphic_function_vf2_args_t *args) { |
615 | |
616 | long int no_of_nodes1=igraph_vcount(graph1), |
617 | no_of_nodes2=igraph_vcount(graph2); |
618 | @@ -1867,6 +1972,14 @@ |
619 | igraph_stack_t path; |
620 | igraph_lazy_adjlist_t inadj1, inadj2, outadj1, outadj2; |
621 | igraph_vector_t indeg1, indeg2, outdeg1, outdeg2; |
622 | + void *isohandler_fn_arg = 0; |
623 | + void *node_compat_fn_arg = 0; |
624 | + void *edge_compat_fn_arg = 0; |
625 | + if (args) { |
626 | + isohandler_fn_arg = args->isohandler_fn_arg; |
627 | + node_compat_fn_arg = args->node_compat_fn_arg; |
628 | + edge_compat_fn_arg = args->edge_compat_fn_arg; |
629 | + } |
630 | |
631 | if (igraph_is_directed(graph1) != igraph_is_directed(graph2)) { |
632 | IGRAPH_ERROR("Cannot compare directed and undirected graphs", |
633 | @@ -2115,6 +2228,9 @@ |
634 | if (vertex_color1 && VECTOR(*vertex_color1)[cand1] != VECTOR(*vertex_color2)[cand2]) { |
635 | end=1; |
636 | } |
637 | + if (node_compat_fn && !node_compat_fn(graph1, graph2, cand1, cand2, node_compat_fn_arg)) { |
638 | + end=1; |
639 | + } |
640 | |
641 | for (i=0; !end && i<igraph_vector_size(inneis_1); i++) { |
642 | long int node=VECTOR(*inneis_1)[i]; |
643 | @@ -2155,6 +2271,9 @@ |
644 | VECTOR(*edge_color2)[(long int)eid2]) { |
645 | end=1; |
646 | } |
647 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
648 | + end=1; |
649 | + } |
650 | } |
651 | } else { |
652 | if (VECTOR(in_2)[node] != 0) { |
653 | @@ -2182,6 +2301,9 @@ |
654 | VECTOR(*edge_color2)[(long int)eid2]) { |
655 | end=1; |
656 | } |
657 | + if (edge_compat_fn && !edge_compat_fn(graph1, graph2, eid1, eid2, edge_compat_fn_arg)) { |
658 | + end=1; |
659 | + } |
660 | } |
661 | } else { |
662 | if (VECTOR(in_2)[node] != 0) { |
663 | @@ -2256,8 +2378,8 @@ |
664 | |
665 | } |
666 | |
667 | - if (matched_nodes==no_of_nodes2 && function) { |
668 | - if (!function(core_1, core_2, arg)) { |
669 | + if (matched_nodes==no_of_nodes2 && isohandler_fn) { |
670 | + if (!isohandler_fn(core_1, core_2, isohandler_fn_arg)) { |
671 | break; |
672 | } |
673 | } |
674 | @@ -2330,6 +2452,15 @@ |
675 | * \param map21 Pointer to a vector ot \c NULL. If not \c NULL, then |
676 | * an isomorphic mapping from \p graph2 to \p graph1 is stored |
677 | * here. |
678 | + * \param node_compat_fn A pointer to a function of type \ref |
679 | + * igraph_isocompat_t. This function will be called by the algorithm to |
680 | + * determine whether two nodes are compatible. |
681 | + * \param edge_compat_fn A pointer to a function of type \ref |
682 | + * igraph_isocompat_t. This function will be called by the algorithm to |
683 | + * determine whether two edges are compatible. |
684 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
685 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
686 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
687 | * \return Error code. |
688 | * |
689 | * Time complexity: exponential. |
690 | @@ -2341,8 +2472,20 @@ |
691 | const igraph_vector_int_t *edge_color1, |
692 | const igraph_vector_int_t *edge_color2, |
693 | igraph_bool_t *iso, igraph_vector_t *map12, |
694 | - igraph_vector_t *map21) { |
695 | - |
696 | + igraph_vector_t *map21, |
697 | + igraph_isocompat_t *node_compat_fn, |
698 | + igraph_isocompat_t *edge_compat_fn, |
699 | + igraph_isomorphic_function_vf2_args_t *args) { |
700 | + |
701 | + igraph_isomorphic_function_vf2_args_t newargs; |
702 | + newargs.isohandler_fn_arg = iso; |
703 | + newargs.node_compat_fn_arg = 0; |
704 | + newargs.edge_compat_fn_arg = 0; |
705 | + if (args) { |
706 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
707 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
708 | + } |
709 | + |
710 | *iso=0; |
711 | IGRAPH_CHECK(igraph_subisomorphic_function_vf2(graph1, graph2, |
712 | vertex_color1, vertex_color2, |
713 | @@ -2350,7 +2493,8 @@ |
714 | map12, map21, |
715 | (igraph_isohandler_t *) |
716 | igraph_i_subisomorphic_vf2, |
717 | - iso)); |
718 | + node_compat_fn, edge_compat_fn, |
719 | + &newargs)); |
720 | if (! *iso) { |
721 | if (map12) { igraph_vector_clear(map12); } |
722 | if (map21) { igraph_vector_clear(map21); } |
723 | @@ -2391,6 +2535,15 @@ |
724 | * \param edge_color2 The edge color vector for the second graph. |
725 | * \param count Pointer to an integer. The number of subgraph |
726 | * isomorphisms is stored here. |
727 | + * \param node_compat_fn A pointer to a function of type \ref |
728 | + * igraph_isocompat_t. This function will be called by the algorithm to |
729 | + * determine whether two nodes are compatible. |
730 | + * \param edge_compat_fn A pointer to a function of type \ref |
731 | + * igraph_isocompat_t. This function will be called by the algorithm to |
732 | + * determine whether two edges are compatible. |
733 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
734 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
735 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
736 | * \return Error code. |
737 | * |
738 | * Time complexity: exponential. |
739 | @@ -2401,8 +2554,20 @@ |
740 | const igraph_vector_int_t *vertex_color2, |
741 | const igraph_vector_int_t *edge_color1, |
742 | const igraph_vector_int_t *edge_color2, |
743 | - igraph_integer_t *count) { |
744 | + igraph_integer_t *count, |
745 | + igraph_isocompat_t *node_compat_fn, |
746 | + igraph_isocompat_t *edge_compat_fn, |
747 | + igraph_isomorphic_function_vf2_args_t *args) { |
748 | |
749 | + igraph_isomorphic_function_vf2_args_t newargs; |
750 | + newargs.isohandler_fn_arg = count; |
751 | + newargs.node_compat_fn_arg = 0; |
752 | + newargs.edge_compat_fn_arg = 0; |
753 | + if (args) { |
754 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
755 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
756 | + } |
757 | + |
758 | *count=0; |
759 | IGRAPH_CHECK(igraph_subisomorphic_function_vf2(graph1, graph2, |
760 | vertex_color1, vertex_color2, |
761 | @@ -2410,7 +2575,8 @@ |
762 | 0, 0, |
763 | (igraph_isohandler_t*) |
764 | igraph_i_count_subisomorphisms_vf2, |
765 | - count)); |
766 | + node_compat_fn, edge_compat_fn, |
767 | + &newargs)); |
768 | return 0; |
769 | } |
770 | |
771 | @@ -2474,6 +2640,15 @@ |
772 | * <function>free()</function> and then 3) call \ref |
773 | * igraph_vector_ptr_destroy() on the pointer vector to deallocate all |
774 | * memory when \p maps is no longer needed. |
775 | + * \param node_compat_fn A pointer to a function of type \ref |
776 | + * igraph_isocompat_t. This function will be called by the algorithm to |
777 | + * determine whether two nodes are compatible. |
778 | + * \param edge_compat_fn A pointer to a function of type \ref |
779 | + * igraph_isocompat_t. This function will be called by the algorithm to |
780 | + * determine whether two edges are compatible. |
781 | + * \param args Extra arguments to supply to functions \p isohandler_fn, \p |
782 | + * node_compat_fn, \p edge_compat_fn. These arguments are packed into an |
783 | + * \ref igraph_isomorphic_function_vf2_args_t struct. |
784 | * \return Error code. |
785 | * |
786 | * Time complexity: exponential. |
787 | @@ -2485,8 +2660,20 @@ |
788 | const igraph_vector_int_t *vertex_color2, |
789 | const igraph_vector_int_t *edge_color1, |
790 | const igraph_vector_int_t *edge_color2, |
791 | - igraph_vector_ptr_t *maps) { |
792 | + igraph_vector_ptr_t *maps, |
793 | + igraph_isocompat_t *node_compat_fn, |
794 | + igraph_isocompat_t *edge_compat_fn, |
795 | + igraph_isomorphic_function_vf2_args_t *args) { |
796 | |
797 | + igraph_isomorphic_function_vf2_args_t newargs; |
798 | + newargs.isohandler_fn_arg = maps; |
799 | + newargs.node_compat_fn_arg = 0; |
800 | + newargs.edge_compat_fn_arg = 0; |
801 | + if (args) { |
802 | + newargs.node_compat_fn_arg = args->node_compat_fn_arg; |
803 | + newargs.edge_compat_fn_arg = args->edge_compat_fn_arg; |
804 | + } |
805 | + |
806 | igraph_vector_ptr_clear(maps); |
807 | IGRAPH_FINALLY(igraph_i_get_subisomorphisms_free, maps); |
808 | IGRAPH_CHECK(igraph_subisomorphic_function_vf2(graph1, graph2, |
809 | @@ -2495,7 +2682,8 @@ |
810 | 0, 0, |
811 | (igraph_isohandler_t*) |
812 | igraph_i_get_subisomorphisms_vf2, |
813 | - maps)); |
814 | + node_compat_fn, edge_compat_fn, |
815 | + &newargs)); |
816 | IGRAPH_FINALLY_CLEAN(1); |
817 | return 0; |
818 | } |
This is the updated version. I believe it is bug free and ready for merge. I have done my best to keep the documentation updated with these changes.