1use std::collections::HashSet;
22use std::collections::HashMap;
23use std::collections::hash_map::Entry;
24use log::trace;
25
26use crate::graph_engine::model::GraphProxy;
27use crate::graph_engine::model::ProxyNodeId;
28use crate::graph_engine::model::ProxyRelationshipId;
29use crate::model::Node;
30use crate::model::PropertyGraph;
31use crate::model::Relationship;
32
33use super::base_state::*;
34use super::super::super::graph::traits::*;
35use super::super::super::graph::*;
36
37fn inc_in<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
38 base_state.term_in_count += 1;
39 if base_state.out_map.contains_key(v0) {
40 base_state.term_both_count += 1;
41 }
42}
43fn inc_out<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
44 base_state.term_out_count += 1;
45 if base_state.in_map.contains_key(v0) {
46 base_state.term_both_count += 1;
47 }
48}
49
50
51fn inc_term<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
52 if !base_state.in_map.contains_key(v0) {
53 base_state.in_map.insert(*v0, base_state.core_count);
54 inc_in(base_state, v0);
55 }
56 if !base_state.out_map.contains_key(v0) {
57 base_state.out_map.insert(*v0, base_state.core_count);
58 inc_out(base_state, v0);
59 }
60}
61
62fn dec_in<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
63 base_state.term_in_count -= 1;
64 if base_state.out_map.contains_key(v0) && base_state.term_both_count > 0 {
65 base_state.term_both_count -= 1;
66 }
67}
68fn dec_out<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
69 base_state.term_out_count -= 1;
70 if base_state.in_map.contains_key(v0) && base_state.term_both_count > 0 {
71 base_state.term_both_count -= 1;
72 }
73}
74fn dec_in_term<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
75 if let Some(in_count) = base_state.in_map.get(v0) {
76 if *in_count == base_state.core_count {
77 base_state.in_map.remove(v0);
78 dec_in(base_state, v0);
79 }
80 }
81}
82
83fn dec_out_term<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, v0: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
84 if let Some(out_count) = base_state.out_map.get(v0) {
85 if *out_count == base_state.core_count {
86 base_state.out_map.remove(v0);
87 dec_out(base_state, v0);
88 }
89 }
90}
91
92fn inc_source<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, ancestor: NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
93 if let Entry::Vacant(e) = base_state.in_map.entry(ancestor) {
94 e.insert(base_state.core_count);
95 inc_in(base_state, &ancestor);
96 }
97}
98
99fn inc_target<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, successor: NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
100 if let Entry::Vacant(e) = base_state.out_map.entry(successor) {
101 e.insert(base_state.core_count);
102 inc_out(base_state, &successor);
103 }
104}
105
106fn dec_source<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, source: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
107 if let Some(in_count) = base_state.in_map.get(source) {
108 if *in_count == base_state.core_count {
109 base_state.in_map.remove(source);
110 dec_in(base_state, source);
111 }
112 }
113}
114
115fn dec_target<NID0, NID1>(base_state: &mut BaseState<NID0, NID1>, target: &NID0) where NID0: std::hash::Hash + Eq + Copy, NID1: std::hash::Hash + Eq + Copy {
116 if let Some(out_count) = base_state.out_map.get(target) {
117 if *out_count == base_state.core_count {
118 base_state.out_map.remove(target);
119 dec_out(base_state, target);
120 }
121 }
122}
123
124pub fn push_state_0(base_state: &mut BaseState<NodeIndex, ProxyNodeId>, graph: &PropertyGraph, v0: &NodeIndex, v1: &ProxyNodeId) {
125 base_state.core_map.insert(*v0, *v1);
126 base_state.core_count += 1;
127
128 inc_term(base_state, v0);
129
130 for edge_index in graph.in_edges(v0) {
131 let ancestor = graph.get_source_index(&edge_index);
132 inc_source(base_state, ancestor);
133 }
134 for edge_index in graph.out_edges(v0) {
135 let successor = graph.get_target_index(&edge_index);
136 inc_target(base_state, successor);
137 }
138}
139
140pub fn pop_state_0(base_state: &mut BaseState<NodeIndex, ProxyNodeId>, graph: &PropertyGraph, v0: &NodeIndex) {
141 if base_state.core_count == 0 {
142 return;
143 }
144
145 dec_in_term(base_state, v0);
146 for in_edge in graph.in_edges(v0) {
147 let source = graph.get_source_index(&in_edge);
148 dec_source(base_state, &source);
149 }
150
151 dec_out_term(base_state, v0);
152
153 for out_edge in graph.out_edges(v0) {
154 let target = graph.get_target_index(&out_edge);
155 dec_target(base_state, &target);
156 }
157
158 base_state.core_count -= 1;
159
160 base_state.core_map.remove(v0);
161}
162
163
164pub fn push_state_1(base_state: &mut BaseState<ProxyNodeId, NodeIndex>, graph: & mut GraphProxy, v0: &ProxyNodeId, v1: &NodeIndex) -> Option<()> {
165 base_state.core_count += 1;
166 base_state.core_map.insert(*v0, *v1);
167 inc_term(base_state, v0);
168 for (_edge_index, ancestor, _rel) in graph.in_edges(v0)? {
169 inc_source(base_state, ancestor);
170 }
171 for (_edge_index, successor, _rel) in graph.out_edges(v0)? {
172 inc_target(base_state, successor);
173 }
174 Some(())
175}
176
177pub fn pop_state_1(base_state: &mut BaseState<ProxyNodeId, NodeIndex>, graph: &mut GraphProxy, v0: &ProxyNodeId) -> Option<()> {
178 if base_state.core_count == 0 {
179 return Some(());
180 }
181
182 dec_in_term(base_state, v0);
183
184 for (_in_edge, source, _rel) in graph.in_edges(v0)? {
185 dec_source(base_state, &source);
186 }
187
188 dec_out_term(base_state, v0);
189
190 for (_out_edge, target, _rel) in graph.out_edges(v0)? {
191 dec_target(base_state, &target);
192 }
193
194 base_state.core_map.remove(v0);
195
196 base_state.core_count -= 1;
197 Some(())
198}
199
200pub struct State<'g0, VCOMP, ECOMP>
201 where VCOMP: Fn(&Node, &Node) -> bool, ECOMP: Fn(&Relationship, &Relationship) -> bool {
202 graph_0: &'g0 PropertyGraph,
203 vertex_comp: VCOMP,
204 edge_comp: ECOMP,
205 base_state_0: BaseState<NodeIndex, ProxyNodeId>,
206 base_state_1: BaseState<ProxyNodeId, NodeIndex>,
207
208}
209
210impl <'g0, VCOMP, ECOMP> State<'g0, VCOMP, ECOMP>
211 where VCOMP: Fn(&Node, &Node) -> bool, ECOMP: Fn(&Relationship, &Relationship) -> bool {
212
213
214 pub fn new(graph_0: &'g0 PropertyGraph, vcomp: VCOMP, ecomp: ECOMP) -> Self {
215 State {
216 graph_0,
217 vertex_comp: vcomp,
218 edge_comp: ecomp,
219 base_state_0: BaseState::new(),
220 base_state_1: BaseState::new(),
221 }
222 }
223
224 pub fn push(&mut self, v0: &NodeIndex, v1: &ProxyNodeId, graph_1: &mut GraphProxy<'_>) {
225 push_state_0(&mut self.base_state_0, self.graph_0, v0, v1);
226 push_state_1(&mut self.base_state_1, graph_1, v1, v0);
227 }
228
229 pub fn pop(&mut self, v0: &NodeIndex, _v1: &ProxyNodeId, graph_1: &mut GraphProxy<'_>) -> Option<()> {
230 if let Some(&w) = self.base_state_0.core(v0) {
231 pop_state_0(&mut self.base_state_0, self.graph_0, v0);
232 pop_state_1(&mut self.base_state_1, graph_1, &w);
233 }
234 Some(())
235 }
236
237 pub fn feasible(&mut self, v_new: &NodeIndex, w_new: &ProxyNodeId, graph_1: &mut GraphProxy<'_>) -> Option<bool> {
238 trace!("feasible ids: {:?} {:?}", v_new, w_new);
239 let v = self.graph_0.get_node_ref(v_new);
240 let w = graph_1.get_node_ref(w_new)?;
241 trace!("feasible nodes: {:?} {:?}", v, w);
242 if !(self.vertex_comp)(v, w) {
243 trace!("nodes mismatch: {:?} {:?}", v, w);
244 Some(false)
245 } else {
246 trace!("vertex match: {:?} {:?}", v, w);
247 let mut term_in0_count = 0;
248 let mut term_out0_count = 0;
249 let mut rest0_count = 0;
250
251 {
252 let mut matched_edge_set = HashSet::new();
253 for edge_index in self.graph_0.in_edges(v_new) {
254 let source_index = self.graph_0.get_source_index(&edge_index);
255 if !self.inc_counters_match_edge_0(true, &mut term_in0_count, &mut term_out0_count, &mut rest0_count, v_new, &source_index, w_new, &edge_index,
256 &mut matched_edge_set, graph_1)? {
257 return Some(false);
258 }
259 }
260 }
261 {
262 let mut matched_edge_set = HashSet::new();
263 for edge_index in self.graph_0.out_edges(v_new) {
264 let target_index = self.graph_0.get_target_index(&edge_index);
265 if !self.inc_counters_match_edge_0(false, &mut term_in0_count, &mut term_out0_count, &mut rest0_count, v_new, &target_index, w_new, &edge_index,
266 &mut matched_edge_set, graph_1)? {
267 return Some(false);
268 }
269 }
270 }
271
272
273 let mut term_in1_count = 0;
274 let mut term_out1_count = 0;
275 let mut rest1_count = 0;
276 {
277 let mut matched_edge_set = HashSet::new();
278 for (edge_index, source_index, _rel) in graph_1.in_edges(w_new)? {
279 if !self.inc_counters_match_edge_1(true, &mut term_in1_count, &mut term_out1_count, &mut rest1_count, w_new, &source_index, v_new, &edge_index,
280 &mut matched_edge_set)? {
281 return Some(false);
282 }
283 }
284 }
285 {
286 let mut matched_edge_set = HashSet::new();
287 for (edge_index, target_index, _rel) in graph_1.out_edges(w_new)? {
288 if !self.inc_counters_match_edge_1(false, &mut term_in1_count, &mut term_out1_count, &mut rest1_count, w_new, &target_index, v_new, &edge_index,
289 &mut matched_edge_set)? {
290 return Some(false);
291 }
292 }
293 }
294 Some(term_in0_count <= term_in1_count && term_out0_count <= term_out1_count && rest0_count <= rest1_count)
295 }
296 }
297
298 fn inc_counters_match_edge_0(&mut self, is_inbound: bool, term_in: &mut i32, term_out: &mut i32, rest: &mut i32, v_new: &NodeIndex, v_adj: &NodeIndex, w_new: &ProxyNodeId, edge_index: &EdgeIndex, matched_edge_set: &mut HashSet<ProxyRelationshipId>, graph_1: &mut GraphProxy<'_>) -> Option<bool> {
299 let r0 = self.graph_0.get_relationship_ref(edge_index);
300 if self.base_state_0.in_core(v_adj) || v_new == v_adj {
301 let mut w = *w_new;
302 if v_adj != v_new {
303 if let Some(ws) = self.base_state_0.core(v_adj) {
304 w = *ws;
305 }
306 }
307
308 if is_inbound {
309 if !self.edge_exists_1(&w, w_new, r0, matched_edge_set, graph_1)? {
310 return Some(false);
311 }
312 } else if !self.edge_exists_1(w_new, &w, r0, matched_edge_set, graph_1)? {
313 return Some(false);
314 }
315 } else {
316 if self.base_state_0.in_depth(v_adj) > 0 {
317 *term_in += 1;
318 }
319 if self.base_state_0.out_depth(v_adj) > 0 {
320 *term_out += 1;
321 }
322 if self.base_state_0.in_depth(v_adj) == 0 && self.base_state_0.out_depth(v_adj) == 0 {
323 *rest += 1;
324 }
325 }
326 Some(true)
327 }
328
329 fn edge_exists_0(&mut self, source: &NodeIndex, target: &NodeIndex, r1: &Relationship, matched_edge_set: &mut HashSet<EdgeIndex>) -> Option<bool> {
330 for out_edge_index in self.graph_0.out_edges(source) {
331 let curr_target = self.graph_0.get_target_index(&out_edge_index);
332 if curr_target == *target && !matched_edge_set.contains(&out_edge_index) {
333 let r = self.graph_0.get_relationship_ref(&out_edge_index);
334 if (self.edge_comp)(r, r1) {
335 matched_edge_set.insert(out_edge_index);
336 return Some(true);
337 }
338 }
339 }
340 Some(false)
341 }
342
343 fn edge_exists_1(&mut self, source: &ProxyNodeId, target: &ProxyNodeId, r0: &Relationship, matched_edge_set: &mut HashSet<ProxyRelationshipId>, graph_1: &mut GraphProxy<'_>) -> Option<bool> {
344 for (out_edge_index, curr_target, r) in graph_1.out_edges(source)? {
345 if curr_target == *target && !matched_edge_set.contains(&out_edge_index) && (self.edge_comp)(r0, &r){
346 matched_edge_set.insert(out_edge_index);
347 return Some(true);
348 }
349 }
350 Some(false)
351 }
352
353 fn inc_counters_match_edge_1(&self, _is_inbound: bool, term_in: &mut i32, term_out: &mut i32, rest: &mut i32, w_new: &ProxyNodeId, w_adj: &ProxyNodeId, _v_new: &NodeIndex, _edge_index: &ProxyRelationshipId, _matched_edge_set: &mut HashSet<EdgeIndex>) -> Option<bool> {
354 if self.base_state_1.in_core(w_adj) || w_new == w_adj {
355
356 } else {
357 if self.base_state_1.in_depth(w_adj) > 0 {
358 *term_in += 1;
359 }
360 if self.base_state_1.out_depth(w_adj) > 0 {
361 *term_out += 1;
362 }
363 if self.base_state_1.in_depth(w_adj) == 0 && self.base_state_1.out_depth(w_adj) == 0 {
364 *rest += 1;
365 }
366 }
367 Some(true)
368 }
369
370 pub fn possible_candidate_0(&self, v0: &NodeIndex) -> bool {
371 if self.base_state_0.term_both() && self.base_state_1.term_both() {
372 self.base_state_0.term_both_vertex(v0)
373 } else if self.base_state_0.term_out() && self.base_state_1.term_out() {
374 self.base_state_0.term_out_vertex(v0)
375 } else if self.base_state_0.term_in() && self.base_state_1.term_in() {
376 self.base_state_0.term_in_vertex(v0)
377 } else {
378 !self.base_state_0.in_core(v0)
379 }
380 }
381
382 pub fn possible_candidate_1(&self, v1: &ProxyNodeId) -> bool {
383 trace!("possible candidate: {:?}", v1);
384 if self.base_state_0.term_both() && self.base_state_1.term_both() {
385 self.base_state_1.term_both_vertex(v1)
386 } else if self.base_state_0.term_out() && self.base_state_1.term_out() {
387 self.base_state_1.term_out_vertex(v1)
388 } else if self.base_state_0.term_in() && self.base_state_1.term_in() {
389 self.base_state_1.term_in_vertex(v1)
390 } else {
391 !self.base_state_1.in_core(v1)
392 }
393 }
394
395 pub fn success(&self) -> bool {
396 self.base_state_0.count() == self.graph_0.nodes_len()
397 }
398
399 pub fn valid(&self) -> bool {
400 let term_set_0 = self.base_state_0.term_set();
401 let term_set_1 = self.base_state_1.term_set();
402 term_set_0.0 <= term_set_1.0 && term_set_0.1 <= term_set_1.1 && term_set_0.2 <= term_set_1.2
403 }
404
405 pub fn call_back<CALLBACK>(&mut self, callback: &mut CALLBACK, graph_1: &mut GraphProxy<'_>) -> Option<bool>
406 where CALLBACK: FnMut(&HashMap<NodeIndex, ProxyNodeId>, &HashMap<ProxyNodeId, NodeIndex>, &PropertyGraph, &mut GraphProxy<'_>) -> Option<bool>
407 {
408 callback(self.base_state_0.get_map(), self.base_state_1.get_map(), self.graph_0, graph_1)
409 }
410
411}