1use std::collections::{HashMap, HashSet, VecDeque};
2use log::{info, warn};
3use serde::{Serialize, Deserialize};
8use std::fs::File;
9use std::io::{BufReader, BufWriter};
10use std::error::Error;
11
12
13use graph_base::interfaces::{edge::{DirectedHyperedge, Hyperedge}, graph::SingleId, hypergraph::{ContainedDirectedHyperedge, ContainedHyperedge, DirectedHypergraph, Hypergraph}, typed::{Type, Typed}};
14
15use crate::{algorithm::simulation, utils::logger::init_global_logger_once};
16use crate::utils::logger::TraceLog;
17
18pub trait LMatch {
19 type Edge;
20 fn new() -> Self;
22 fn l_match_with_node_mut(&mut self, e: &Self::Edge, e_prime: &Self::Edge, u: usize) -> &HashSet<usize>;
23 fn l_match_with_node(&self, e: &Self::Edge, e_prime: &Self::Edge, u: usize) -> &HashSet<usize>;
24 fn dom(&self, e: &Self::Edge, e_prime: &Self::Edge) -> impl Iterator<Item = &usize>;
25}
26
27#[derive(Hash)]
28pub struct SematicCluster<'a, E: Hyperedge> {
29 id: usize,
30 hyperedges: Vec<&'a E>,
31}
32
33impl<'a, E: Hyperedge> SematicCluster<'a, E> {
34
35 pub fn new(id: usize, hyperedges: Vec<&'a E>) -> Self {
36 Self {
37 id,
38 hyperedges,
39 }
40 }
41
42 pub fn id(&self) -> usize {
43 self.id
44 }
45
46 pub fn hyperedges(&self) -> &Vec<&'a E> {
47 &self.hyperedges
48 }
49}
50
51pub trait Delta<'a> {
52 type Node;
53 type Edge: Hyperedge;
54 fn get_sematic_clusters(&'a self, u: &'a Self::Node, v: &'a Self::Node) -> &'a Vec<(SematicCluster<'a, Self::Edge>, SematicCluster<'a, Self::Edge>)>;
55}
56
57pub trait DMatch<'a> {
58 type Edge: Hyperedge;
59 fn d_match(&self, e: &SematicCluster<'a, Self::Edge>, e_prime: &SematicCluster<'a, Self::Edge>) -> &HashSet<(usize, usize)>;
61}
62
63pub trait LPredicate<'a>: Hypergraph<'a> {
64 fn l_predicate_node(&'a self, u: &'a Self::Node, v: &'a Self::Node) -> bool;
65 fn l_predicate_edge(&'a self, e: &'a Self::Edge, e_prime: &'a Self::Edge) -> bool;
66 fn l_predicate_set(&'a self, x: &HashSet<&'a Self::Node>, y: &HashSet<&'a Self::Node>) -> bool;
67}
68
69pub trait HyperSimulation<'a>: Hypergraph<'a> {
70 fn get_simulation_fixpoint(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
71 fn get_simulation_recursive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
72 fn get_simulation_naive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
73 fn get_soft_simulation_naive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
74 fn get_hyper_simulation_naive(&'a self, other: &'a Self, delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>, d_match: & impl DMatch<'a, Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
75 fn get_hyper_simulation_effect(&'a self, other: &'a Self, delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>, d_match: & impl DMatch<'a, Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
76 fn get_hyper_simulation_strict(&'a self, other: &'a Self, delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>, d_match: & impl DMatch<'a, Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>>;
77}
78impl<'a, H> HyperSimulation<'a> for H
97where H: Hypergraph<'a> + Typed<'a> + LPredicate<'a> + ContainedHyperedge<'a> {
98 fn get_simulation_fixpoint(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
99 todo!()
100 }
101
102 fn get_simulation_recursive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
103 todo!()
104 }
105
106 fn get_simulation_naive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
107
108 init_global_logger_once("hyper-simulation.log");
120
121 info!("Start Naive Hyper Simulation");
122
123 let self_contained_hyperedge = self.get_hyperedges_list();
124 let other_contained_hyperedge = other.get_hyperedges_list();
125
126 let mut simulation: HashMap<&Self::Node, HashSet<&Self::Node>> = self.nodes().map(|u| {
127 let res = other.nodes().filter(|v| {
128 if self.type_same(u, *v) {
129 let mut l_match_intersection: Option<HashSet<usize>> = None;
132 for e in self.contained_hyperedges(&self_contained_hyperedge, u) {
133 let mut l_match_union: HashSet<usize> = HashSet::new();
134 for e_prime in other.contained_hyperedges(&other_contained_hyperedge, v) {
135 if self.l_predicate_edge(e, e_prime) {
136 let id_set = l_match.l_match_with_node(e, e_prime, u.id());
138 l_match_union = l_match_union.union(&id_set).copied().collect();
139 }
140 }
141 l_match_intersection = match l_match_intersection {
142 Some(ref acc) => Some(acc.intersection(&l_match_union).copied().collect()),
143 None => Some(l_match_union),
144 };
145 }
146 if let Some(l_match_intersection) = l_match_intersection {
147 if l_match_intersection.contains(&v.id()){
148 return true;
149 }
150 }
151 }
152 false
153 }).collect();
154 (u, res)
155 }).collect();
156
157 info!("END Initial, sim: is ");
158 for (u, v_set) in &simulation {
159 info!("\tsim({}) = {:?}", u.id(), v_set.iter().map(|v| v.id()).collect::<Vec<_>>());
160 }
161
162
163 let mut changed = true;
164 while changed {
165 changed = false;
166 for u in self.nodes() {
167 let mut need_delete = Vec::new();
168 for v in simulation.get(u).unwrap() {
169 info!("Checking {} -> {}", u.id(), v.id());
170 let mut _delete = true;
171 for e in self.contained_hyperedges(&self_contained_hyperedge, u) {
172 if !_delete {
173 break;
174 }
175 for e_prime in other.contained_hyperedges(&other_contained_hyperedge, v) {
176 if self.l_predicate_edge(e, e_prime) {
177 if l_match.dom(e, e_prime).all(|u_prime| {
178 l_match.l_match_with_node(e, e_prime, u_prime.clone()).iter().map(|id| {other.get_node_by_id(*id)}).any(|v_prime| {
179 if let Some(v_prime) = v_prime {
180 return simulation.get(u).unwrap().contains(v_prime);
181 } else {
182 return false;
183 }
184 })
185 }) {
186 info!("Keeping {} -> {}", u.id(), v.id());
187 _delete = false;
188 break;
189 }
190 }
191 }
192 }
193 if _delete {
194 info!("Deleting {} -> {}", u.id(), v.id());
195 need_delete.push(v.clone());
196 }
197 }
198 for v in need_delete {
199 simulation.get_mut(u).unwrap().remove(v);
200 changed = true;
201 }
202 }
203 }
204
205 simulation
206 }
207
208 fn get_soft_simulation_naive(&'a self, other: &'a Self, l_match: &mut impl LMatch<Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
209 init_global_logger_once("hyper-simulation.log");
210
211 info!("Start Naive Hyper Simulation");
212
213 let mut l_predicate_edges: HashMap<(usize, usize), Vec<(&Self::Edge, &Self::Edge)>> = HashMap::new();
217 for e in self.hyperedges() {
218 for e_prime in other.hyperedges() {
219 if self.l_predicate_edge(e, e_prime) {
220 for u in e.id_set() {
221 for v in e_prime.id_set() {
222 l_predicate_edges.entry((u, v)).or_default().push((e, e_prime));
223 }
224 }
225 }
226 }
227 }
228
229 let mut simulation: HashMap<&'a Self::Node, HashSet<&'a Self::Node>> = self.nodes().map(|u| {
230 let res = other.nodes().filter(|v| {
231 if self.type_same(u, *v) {
232 if let Some(edge_pairs) = l_predicate_edges.get(&(u.id(), v.id())) {
233 for (e, e_prime) in edge_pairs {
234 let id_set = l_match.l_match_with_node(e, e_prime, u.id());
235 if !id_set.contains(&v.id()) {
236 return false;
237 }
238 }
239 return true;
240 } else {
241 return true;
242 }
243 }
244 false
245 }).collect();
246 (u, res)
247 }).collect();
248
249 info!("END Initial, sim: is ");
250 for (u, v_set) in &simulation {
251 info!("\tsim({}) = {:?}", u.id(), v_set.iter().map(|v| v.id()).collect::<Vec<_>>());
252 }
253
254
255 let mut changed = true;
256 while changed {
257 changed = false;
258 for u in self.nodes() {
259 let mut need_delete = Vec::new();
260 for v in simulation.get(u).unwrap() {
261 info!("Checking {} -> {}", u.id(), v.id());
262 let mut _delete = false;
263
264 if let Some(edge_pairs) = l_predicate_edges.get(&(u.id(), v.id())) {
265 for (e, e_prime) in edge_pairs {
266 if l_match.dom(e, e_prime).all(|u_prime| {
267 l_match.l_match_with_node(e, e_prime, u_prime.clone()).iter().map(|id| {other.get_node_by_id(*id)}).any(|v_prime| {
268 if let Some(v_prime) = v_prime {
269 return simulation.get(u).unwrap().contains(v_prime);
270 } else {
271 return false;
272 }
273 })
274 }) {
275 info!("Keeping {} -> {}", u.id(), v.id());
276 _delete = true;
277 break;
278 }
279 }
280 }
281
282 if _delete {
283 info!("Deleting {} -> {}", u.id(), v.id());
284 need_delete.push(v.clone());
285 }
286 }
287
288 for v in need_delete {
289 simulation.get_mut(u).unwrap().remove(v);
290 changed = true;
291 }
292 }
293 }
294
295 simulation
296
297 }
298
299 fn get_hyper_simulation_naive(&'a self, other: &'a Self, delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>, d_match: & impl DMatch<'a, Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
300 init_global_logger_once("logs/hyper-simulation.log");
301 let mut hs_trace = HyperSimulationTrace::new();
302 let mut simulation: HashMap<&'a Self::Node, HashSet<&'a Self::Node>> = self.nodes().map(|u| {
303 let res = other.nodes().filter(|v| {
304 if self.type_same(u, *v) {
305 let sematic_clusters = delta.get_sematic_clusters(u, v);
306 for (cluster_u, cluster_v) in sematic_clusters {
307 let d_match_set = d_match.d_match(cluster_u, cluster_v);
308 if !d_match_set.contains(&(u.id(), v.id())) {
309 hs_trace.add_base_event(cluster_u.id, d_match_set.clone());
311 return false;
312 }
313 }
314 return true;
315 }
316 false
317 }).collect();
318 (u, res)
319 }).collect();
320
321 info!("END Initial, raw-sim: is ");
322 for (u, v_set) in &simulation {
323 info!("\tsim({}) = {:?}", u.id(), v_set.iter().map(|v| v.id()).collect::<Vec<_>>());
324 }
325
326 let mut simulation_by_id: HashSet<(usize, usize)> = simulation.iter().flat_map(|(u, v_set)| {
327 v_set.iter().map(move |v| (u.id(), v.id()))
328 }).collect();
329
330 let mut changed = true;
331 while changed {
332 changed = false;
333 for u in self.nodes() {
334 let mut need_delete = Vec::new();
335 for v in simulation.get(u).unwrap() {
336 info!("Checking {} -> {}", u.id(), v.id());
337 let mut _delete = false;
338
339 let sematic_clusters = delta.get_sematic_clusters(u, v);
340 for (cluster_u, cluster_v) in sematic_clusters {
341 let d_relation = d_match.d_match(cluster_u, cluster_v);
342 if !d_relation.is_subset(&simulation_by_id) {
344 info!("Deleting {} -> {}", u.id(), v.id());
345 let uncoverd: HashSet<(usize, usize)> = d_relation.difference(&simulation_by_id).copied().collect();
347 hs_trace.add_derivation_event(cluster_u.id, uncoverd);
348 _delete = true;
349 break;
350 }
351 }
352
353 if _delete {
354 need_delete.push(v.clone());
355 }
356 }
357
358 for v in need_delete {
359 simulation.get_mut(u).unwrap().remove(v);
360 simulation_by_id.remove(&(u.id(), v.id()));
361 changed = true;
362 }
363 }
364 }
365
366 hs_trace.store_trace_file("logs/hyper_simulation.trace").unwrap();
367
368 return simulation;
369 }
370
371 fn get_hyper_simulation_strict(&'a self, other: &'a Self, delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>, d_match: & impl DMatch<'a, Edge = Self::Edge>) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
372 init_global_logger_once("logs/hyper-simulation.log");
373 let mut hs_trace = HyperSimulationTrace::new();
374 let mut simulation: HashMap<&'a Self::Node, HashSet<&'a Self::Node>> = self.nodes().map(|u| {
375 let res = other.nodes().filter(|v| {
376 if self.type_same(u, *v) {
377 let sematic_clusters = delta.get_sematic_clusters(u, v);
378 if sematic_clusters.len() == 0 {
380 info!("Deleting {} -> {} because no sematic cluster", u.id(), v.id());
381 return false;
382 }
383 info!("Checking {} -> {}, sematic clusters size: {}", u.id(), v.id(), sematic_clusters.len());
384 for (cluster_u, cluster_v) in sematic_clusters {
385 let d_match_set = d_match.d_match(cluster_u, cluster_v);
386 if !d_match_set.contains(&(u.id(), v.id())) {
387 hs_trace.add_base_event(cluster_u.id, d_match_set.clone());
389 return false;
390 }
391 }
392 return true;
393 }
394 false
395 }).collect();
396 (u, res)
397 }).collect();
398
399 info!("END Initial, raw-sim: is ");
400 for (u, v_set) in &simulation {
401 info!("\tsim({}) = {:?}", u.id(), v_set.iter().map(|v| v.id()).collect::<Vec<_>>());
402 }
403
404 let mut simulation_by_id: HashSet<(usize, usize)> = simulation.iter().flat_map(|(u, v_set)| {
405 v_set.iter().map(move |v| (u.id(), v.id()))
406 }).collect();
407
408 let mut changed = true;
409 while changed {
410 changed = false;
411 for u in self.nodes() {
412 let mut need_delete = Vec::new();
413 for v in simulation.get(u).unwrap() {
414 info!("Checking {} -> {}", u.id(), v.id());
415 let mut _delete = false;
416
417 let sematic_clusters = delta.get_sematic_clusters(u, v);
418 for (cluster_u, cluster_v) in sematic_clusters {
419 let d_relation = d_match.d_match(cluster_u, cluster_v);
420 if !d_relation.is_subset(&simulation_by_id) {
422 info!("Deleting {} -> {}", u.id(), v.id());
423 let uncoverd: HashSet<(usize, usize)> = d_relation.difference(&simulation_by_id).copied().collect();
425 hs_trace.add_derivation_event(cluster_u.id, uncoverd);
426 _delete = true;
427 break;
428 }
429 }
430
431 if _delete {
432 need_delete.push(v.clone());
433 }
434 }
435
436 for v in need_delete {
437 simulation.get_mut(u).unwrap().remove(v);
438 simulation_by_id.remove(&(u.id(), v.id()));
439 changed = true;
440 }
441 }
442 }
443
444 hs_trace.store_trace_file("logs/hyper_simulation.trace").unwrap();
445
446 return simulation;
447 }
448
449 fn get_hyper_simulation_effect(
450 &'a self,
451 other: &'a Self,
452 delta: &'a impl Delta<'a, Node = Self::Node, Edge = Self::Edge>,
453 d_match: &impl DMatch<'a, Edge = Self::Edge>,
454 ) -> HashMap<&'a Self::Node, HashSet<&'a Self::Node>> {
455 let mut id_to_u: HashMap<usize, &'a Self::Node> = HashMap::new();
457 let mut id_to_v: HashMap<usize, &'a Self::Node> = HashMap::new();
458
459 let mut hc_map: HashMap<(usize, usize), Vec<((usize, usize), HashSet<(usize, usize)>)>> = HashMap::new();
461
462 let mut pi: HashSet<(usize, usize)> = HashSet::new();
464
465 for u in self.nodes() {
471 id_to_u.insert(u.id(), u);
472 for v in other.nodes() {
473 id_to_v.insert(v.id(), v);
474
475 if self.type_same(u, v) {
476 let sematic_clusters = delta.get_sematic_clusters(u, v);
477 let mut valid = true;
478 let mut local_clusters = Vec::new();
479
480 for (cluster_u, cluster_v) in sematic_clusters {
481 let cu_id = cluster_u.id;
482 let cv_id = cluster_v.id;
483 let d_match_set = d_match.d_match(cluster_u, cluster_v);
484
485 if !d_match_set.contains(&(u.id(), v.id())) {
487 valid = false;
488 break; }
490 local_clusters.push(((cu_id, cv_id), d_match_set.clone()));
491 }
492
493 if valid {
494 pi.insert((u.id(), v.id()));
495 hc_map.insert((u.id(), v.id()), local_clusters);
496 }
497 }
498 }
499 }
500
501 let mut a_cluster_d_match: HashMap<(usize, usize), HashSet<(usize, usize)>> = HashMap::new();
503
504 let mut d_cluster: HashMap<(usize, usize), HashSet<(usize, usize)>> = HashMap::new();
507 let mut d_pair: HashMap<(usize, usize), HashSet<(usize, usize)>> = HashMap::new();
509
510 for (&(u_id, v_id), clusters) in &hc_map {
511 for ((cu_id, cv_id), d_match_set) in clusters {
512 let c_pair = (*cu_id, *cv_id);
513
514 d_cluster.entry(c_pair).or_default().insert((u_id, v_id));
516
517 if !a_cluster_d_match.contains_key(&c_pair) {
519 a_cluster_d_match.insert(c_pair, d_match_set.clone());
520
521 for &(up_id, vp_id) in d_match_set {
522 d_pair.entry((up_id, vp_id)).or_default().insert(c_pair);
523 }
524 }
525 }
526 }
527
528 let mut v_c: HashSet<(usize, usize)> = HashSet::new();
530 for (c_pair, d_match_set) in &a_cluster_d_match {
531 if d_match_set.is_subset(&pi) {
533 v_c.insert(*c_pair);
534 }
535 }
536
537 let mut q: VecDeque<(usize, usize)> = VecDeque::new();
539 let mut pi_retained = pi.clone();
540
541 for &(u_id, v_id) in &pi {
542 let mut all_in_vc = true;
543 if let Some(clusters) = hc_map.get(&(u_id, v_id)) {
544 for (c_pair, _) in clusters {
545 if !v_c.contains(c_pair) {
546 all_in_vc = false;
547 break;
548 }
549 }
550 }
551
552 if !all_in_vc {
553 q.push_back((u_id, v_id)); pi_retained.remove(&(u_id, v_id)); }
556 }
557 pi = pi_retained;
558
559 while let Some((up_id, vp_id)) = q.pop_front() {
563 if let Some(dependent_clusters) = d_pair.get(&(up_id, vp_id)) {
565 for c_pair in dependent_clusters {
566 if v_c.contains(c_pair) {
568 v_c.remove(c_pair); if let Some(dependent_node_pairs) = d_cluster.get(c_pair) {
572 for node_pair in dependent_node_pairs {
573 if pi.contains(node_pair) {
574 pi.remove(node_pair);
575 q.push_back(*node_pair);
576 }
577 }
578 }
579 }
580 }
581 }
582 }
583
584 let mut result: HashMap<&'a Self::Node, HashSet<&'a Self::Node>> =
589 self.nodes().map(|u| (u, HashSet::new())).collect();
590
591 for (u_id, v_id) in pi {
592 let u_node = id_to_u[&u_id];
594 let v_node = id_to_v[&v_id];
595 if let Some(set) = result.get_mut(u_node) {
596 set.insert(v_node);
597 }
598 }
599
600 result
601 }
602}
603
604#[derive(Serialize, Deserialize, Debug, PartialEq)]
605pub struct HyperSimulationTrace {
606 events: Vec<HSEvent>
607}
608
609impl HyperSimulationTrace {
610 fn new() -> Self {
611 HyperSimulationTrace {
612 events: Vec::new()
613 }
614 }
615
616 fn add_base_event(&mut self, sc_id: usize, d_match: HashSet<(usize, usize)>) {
617 let event = HSEvent::Base(sc_id, d_match);
618 self.events.push(event);
619 }
620 fn add_derivation_event(&mut self, sc_id: usize, uncoverd: HashSet<(usize, usize)>) {
621 let event = HSEvent::Derivation(sc_id, uncoverd);
622 self.events.push(event);
623 }
624}
625
626impl IntoIterator for HyperSimulationTrace {
627 type Item = HSEvent;
628 type IntoIter = std::vec::IntoIter<HSEvent>;
629
630 fn into_iter(self) -> Self::IntoIter {
631 self.events.into_iter()
632 }
633}
634
635impl<'a> IntoIterator for &'a HyperSimulationTrace {
636 type Item = &'a HSEvent;
637 type IntoIter = std::slice::Iter<'a, HSEvent>;
638
639 fn into_iter(self) -> Self::IntoIter {
640 self.events.iter()
641 }
642}
643
644impl TraceLog for HyperSimulationTrace {
645 fn store_trace_file(self, filename: &'static str) -> Result<(), Box<dyn Error>> {
646 let file = File::create(filename)?;
648 let mut writer = BufWriter::new(file);
649 bincode::serialize_into(&mut writer, &self)?;
650 Ok(())
651 }
652
653 fn get_trace(filename: &'static str) -> Result<Self, Box<dyn Error>> {
654 let file = File::open(filename)?;
655 let mut reader = BufReader::new(file);
656 let file_decoded: HyperSimulationTrace = bincode::deserialize_from(&mut reader)?;
657 Ok(file_decoded)
658 }
659}
660
661#[derive(Serialize, Deserialize, Debug, PartialEq)]
662pub enum HSEvent {
663 Base(usize, HashSet<(usize, usize)>), Derivation(usize, HashSet<(usize, usize)>) }