diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/gspan.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/gspan.rs index 710161e9f3f0ecf2bf232cd494b27942b73b0118..54ce00a22d3116c6eb1d8728ec8eb3049e2717d0 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/gspan.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/gspan.rs @@ -1,12 +1,7 @@ /* * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ -use std::{ - collections::BTreeMap - - , - usize, -}; +use std::collections::BTreeMap; use rustc_hash::FxHashSet; use smartstring::alias::String; @@ -41,12 +36,17 @@ impl GSpan { max_pat_max: usize, directed: bool, ) -> GSpan { - GSpan { trans: graphs, min_sup, inner_min_sup, max_pat_min, max_pat_max, directed } + GSpan { + trans: graphs, + min_sup, + inner_min_sup, + max_pat_min, + max_pat_max, + directed, + } } - pub fn run( - &self, - ) -> (usize, MaxDFSCodeGraphResult) { + pub fn run(&self) -> (usize, MaxDFSCodeGraphResult) { // 0. Prepare the Result let mut result = MaxDFSCodeGraphResult::default(); result.set_config( @@ -59,9 +59,9 @@ impl GSpan { // 1. Find single node frequent subgraph, if requested let mut single_vertex_graph_map: BTreeMap< usize, - BTreeMap, usize)>, + BTreeMap, usize)>, > = BTreeMap::new(); - let mut single_vertex_label_frequent_map: BTreeMap = BTreeMap::new(); // 一个 graph 内重复的 vertex 的频繁度只记录一次 + let mut single_vertex_label_frequent_map: BTreeMap = BTreeMap::new(); // 一个 graph 内重复的 vertex 的频繁度只记录一次 if self.max_pat_min <= 1 { self.find_frequent_single_vertex( &mut single_vertex_graph_map, @@ -72,15 +72,9 @@ impl GSpan { // 2. Report the single vertex subgraphs let mut next_gid: usize = 0; - self.print_frequent_single_vertex( - &mut single_vertex_graph_map, - &mut single_vertex_label_frequent_map, - &mut next_gid, - ); - // 3. Subgraphs > Vertices // root: [from_label][e_label][to_label] -> Projected - let mut root: BTreeMap>> = + let mut root: BTreeMap>> = BTreeMap::new(); for g in &self.trans { for from in &g.vertices { @@ -89,33 +83,28 @@ impl GSpan { continue; } for edge in &edges { - let key_1 = from.label.clone(); + let key_1 = from.label; let root_1 = root.entry(key_1).or_default(); let key_2 = edge.e_label.clone(); let root_2 = root_1.entry(key_2).or_default(); - let key_3 = g.find_vertex(&edge.to).unwrap().label.clone(); + let key_3 = g.get_vertex(edge.to).unwrap().label; let root_3 = root_2.entry(key_3).or_insert(Projected::new()); root_3.push(g.id, edge, None); } } } let mut dfs_code = DFSCode::new(); - for (from_label_key, from_label_value) in root.iter() { + for (&from_label_key, from_label_value) in root.iter() { for (e_label_key, e_label_value) in from_label_value.iter() { - for (to_label_key, to_label_value) in e_label_value.iter() { + for (&to_label_key, to_label_value) in e_label_value.iter() { dfs_code.push( 0, 1, - from_label_key.clone(), + from_label_key, e_label_key.clone(), - to_label_key.clone(), - ); - self.sub_mining( - to_label_value, - &mut dfs_code, - &mut next_gid, - &mut result, + to_label_key, ); + self.sub_mining(to_label_value, &mut dfs_code, &mut next_gid, &mut result); dfs_code.pop_with_set_result(to_label_value, &mut result); } } @@ -125,64 +114,29 @@ impl GSpan { fn find_frequent_single_vertex( &self, - single_vertex_graph_map: &mut BTreeMap, usize)>>, - single_vertex_label_frequent_map: &mut BTreeMap, + single_vertex_graph_map: &mut BTreeMap, usize)>>, + single_vertex_label_frequent_map: &mut BTreeMap, ) { for graph in &self.trans { for vertex in &graph.vertices { - let key = &vertex.label; + let key = vertex.label; let d = single_vertex_graph_map.entry(graph.id).or_default(); - if d.get(key).is_none() { + if d.get(&key).is_none() { single_vertex_label_frequent_map - .entry(key.clone()) + .entry(key) .and_modify(|f| *f += 1) .or_insert(1); } - d.entry(key.clone()) + d.entry(key) .and_modify(|v| { - v.0.insert(vertex.name.clone()); + v.0.insert(vertex.name); v.1 += 1; }) - .or_insert(([vertex.name.clone()].iter().cloned().collect(), 1)); + .or_insert(([vertex.name].iter().copied().collect(), 1)); } } } - fn print_frequent_single_vertex( - &self, - single_vertex_graph_map: &BTreeMap, usize)>>, - single_vertex_label_frequent_map: &BTreeMap, - next_gid: &mut usize, - ) { - for (frequent_label, sup) in single_vertex_label_frequent_map.iter() { - // 判断图之间的支持度 - if sup < &self.min_sup { - continue; - } - - let mapped: Vec<(FxHashSet, usize)> = single_vertex_graph_map - .iter() - .map(|entry| { - entry.1.get(frequent_label).unwrap_or(&(FxHashSet::default(), 0)).clone() - }) - .collect(); - - // 计算图内部最小、最大支持度 - let mut min = usize::MAX; - let mut max = usize::MIN; - for (_, v) in mapped.iter() { - min = min.min(*v); - max = max.max(*v); - } - - if max < self.inner_min_sup { - continue; - } - - *next_gid += 1; - } - } - fn sub_mining( &self, projected: &Projected, @@ -199,11 +153,11 @@ impl GSpan { * mingt be its (n+1)-extension-graphs, hence we enumerate them all. */ let min_rm_path = dfs_code.build_rm_path(); - let min_label = dfs_code.get_dfs(0).from_label.clone(); - let max_to_code = dfs_code.get_dfs(*min_rm_path.get(0).unwrap()).to.clone(); + let min_label = dfs_code.get_dfs(0).from_label; + let max_to_code = dfs_code.get_dfs(*min_rm_path[0]).to; let (new_fwd_root, new_bck_root) = - self.generate_next_root(projected, dfs_code, &min_rm_path, &min_label, max_to_code); + self.generate_next_root(projected, dfs_code, &min_rm_path, min_label, max_to_code); // Test all extended substructures.. // .. backward @@ -212,9 +166,9 @@ impl GSpan { dfs_code.push( max_to_code, *to_key, - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, e_label_key.clone(), - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, ); self.sub_mining(e_label_value, dfs_code, next_gid, result); dfs_code.pop_with_set_result(e_label_value, result); @@ -223,13 +177,13 @@ impl GSpan { // .. forward for (from_key, from_value) in new_fwd_root.iter().rev() { for (e_label_key, e_label_value) in from_value.iter() { - for (to_label_key, to_label_value) in e_label_value.iter() { + for (&to_label_key, to_label_value) in e_label_value.iter() { dfs_code.push( *from_key, max_to_code + 1, - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, e_label_key.clone(), - to_label_key.clone(), + to_label_key, ); self.sub_mining(to_label_value, dfs_code, next_gid, result); dfs_code.pop_with_set_result(to_label_value, result); @@ -243,14 +197,14 @@ impl GSpan { projected: &'a Projected<'a>, dfs_code: &DFSCode, min_rm_path: &Vec, - min_label: &str, + min_label: usize, max_to_code: usize, ) -> ( - BTreeMap>>>, + BTreeMap>>>, BTreeMap>>, ) { // [from][e_label][to_label] -> Projected - let mut new_fwd_root: BTreeMap>> = + let mut new_fwd_root: BTreeMap>> = BTreeMap::new(); // [to][e_label] -> Projected let mut new_bck_root: BTreeMap> = BTreeMap::new(); @@ -264,12 +218,12 @@ impl GSpan { for i in (0..min_rm_path.len()).rev() { let e = get_backward( self.trans.get(gid).unwrap(), - history.histories.get(*min_rm_path.get(i).unwrap()).unwrap(), - history.histories.get(*min_rm_path.get(0).unwrap()).unwrap(), + history.histories.get(min_rm_path[i]).unwrap(), + history.histories.get(min_rm_path[0]).unwrap(), &history, ); if let Some(e) = e { - let key_1 = dfs_code.get_dfs(*min_rm_path.get(i).unwrap()).from; + let key_1 = dfs_code.get_dfs(min_rm_path[i]).from; let root_1 = new_bck_root.entry(key_1).or_default(); let key_2: &String = &e.e_label; let root_2 = root_1.entry(key_2.clone()).or_insert(Projected::new()); @@ -278,28 +232,27 @@ impl GSpan { } // pure forward let edges: Vec<&Edge> = get_forward_pure( - self.trans.get(gid).unwrap(), - history.histories.get(*min_rm_path.get(0).unwrap()).unwrap(), - &min_label, + &self.trans[gid], + history.histories[min_rm_path[0]], + min_label, &history, ); if !edges.is_empty() { for it in &edges { let root_1 = new_fwd_root.entry(max_to_code).or_default(); - let key_2: &String = &it.e_label; + let key_2 = &it.e_label; let root_2 = root_1.entry(key_2.clone()).or_default(); - let key_3: &String = - &self.trans.get(gid).unwrap().find_vertex(&it.to).unwrap().label; - let root_3 = root_2.entry(key_3.clone()).or_insert(Projected::new()); + let key_3 = self.trans[gid].get_vertex(it.to).unwrap().label; + let root_3 = root_2.entry(key_3).or_insert(Projected::new()); root_3.push(gid, it, Some(&a_projected)); } } // backtracked forward for a_rm_path in min_rm_path { let edges: Vec<&Edge> = get_forward_rm_path( - self.trans.get(gid).unwrap(), - history.histories.get(*a_rm_path).unwrap(), - &min_label, + &self.trans[gid], + history.histories[a_rm_path], + min_label, &history, ); if edges.is_empty() { @@ -308,11 +261,10 @@ impl GSpan { for it in &edges { let key_1 = dfs_code.get_dfs(*a_rm_path).from; let root_1 = new_fwd_root.entry(key_1).or_default(); - let key_2: &String = &it.e_label; + let key_2 = &it.e_label; let root_2 = root_1.entry(key_2.clone()).or_default(); - let key_3: &String = - &self.trans.get(gid).unwrap().find_vertex(&it.to).unwrap().label; - let root_3 = root_2.entry(key_3.clone()).or_insert(Projected::new()); + let key_3 = self.trans[gid].get_vertex(it.to).unwrap().label; + let root_3 = root_2.entry(key_3).or_insert(Projected::new()); root_3.push(gid, it, Some(&a_projected)); } } @@ -350,7 +302,7 @@ impl GSpan { if self.max_pat_max >= self.max_pat_min && dfs_code.count_node() > self.max_pat_max { return true; } - + *next_gid += 1; false @@ -371,18 +323,18 @@ impl GSpan { // [from_label][e_label][to_label] -> Projected // BTreeMap 在 Rust 中会自动根据键进行排序 - let mut root: BTreeMap>> = + let mut root: BTreeMap>> = BTreeMap::new(); for from in &graph_is_min.vertices { let edges: Vec<&Edge> = get_forward_edges(&graph_is_min, from); for it in &edges { - let key_1 = &it.from_label; - let root_1 = root.entry(key_1.clone()).or_default(); + let key_1 = it.from_label; + let root_1 = root.entry(key_1).or_default(); let key_2 = &it.e_label; let root_2 = root_1.entry(key_2.clone()).or_default(); - let key_3 = &it.to_label; - let root_3 = root_2.entry(key_3.clone()).or_insert(Projected::new()); + let key_3 = it.to_label; + let root_3 = root_2.entry(key_3).or_insert(Projected::new()); // 创建初始化子图:一个 Edge 就是一个最小子图 root_3.push(graph_is_min.id, it, None); } @@ -398,12 +350,17 @@ impl GSpan { dfs_code_is_min.push( 0, 1, - from_label_map_entry.0.clone(), + *from_label_map_entry.0, e_label_map_entry.0.clone(), - to_label_map_entry.0.clone(), + *to_label_map_entry.0, ); - self.is_min_dfscode(to_label_map_value, dfs_code, &mut dfs_code_is_min, &graph_is_min) + self.is_min_dfscode( + to_label_map_value, + dfs_code, + &mut dfs_code_is_min, + &graph_is_min, + ) } /** @@ -419,7 +376,9 @@ impl GSpan { graph_is_min: &Graph, ) -> bool { let min_rm_path = dfs_code_is_min.build_rm_path(); - let max_to_code = dfs_code_is_min.get_dfs(*min_rm_path.get(0).unwrap()).to.clone(); + let max_to_code = dfs_code_is_min + .get_dfs(min_rm_path[0]) + .to; { // backward 情况下是否最小: [e_label] -> Projected @@ -431,12 +390,15 @@ impl GSpan { dfs_code_is_min.push( max_to_code, new_to, - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, e_label_map_entry.key().clone(), - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, ); let len = dfs_code_is_min.dfs_vec.len(); - if dfs_code.get_dfs(len - 1).ne(dfs_code_is_min.get_dfs(len - 1)) { + if dfs_code + .get_dfs(len - 1) + .ne(dfs_code_is_min.get_dfs(len - 1)) + { return false; } return self.is_min_dfscode( @@ -455,7 +417,7 @@ impl GSpan { dfs_code_is_min, graph_is_min, &min_rm_path, - &max_to_code, + max_to_code, ); if let Some(root) = root { @@ -464,13 +426,16 @@ impl GSpan { dfs_code_is_min.push( new_from, max_to_code + 1, - Vertex::NIL_V_LABEL.into(), + Vertex::NIL_V_LABEL, e_label_map_key.into(), to_label_map_key.into(), ); let len: usize = dfs_code_is_min.dfs_vec.len(); - if dfs_code.get_dfs(len - 1).ne(dfs_code_is_min.get_dfs(len - 1)) { + if dfs_code + .get_dfs(len - 1) + .ne(dfs_code_is_min.get_dfs(len - 1)) + { return false; } return self.is_min_dfscode( @@ -498,7 +463,7 @@ impl GSpan { for i in (1..min_rm_path.len()).rev() { root = self.generate_e_p_map(projected, graph_is_min, &min_rm_path, i); if root.is_some() { - new_to = dfs_code_is_min.get_dfs(*min_rm_path.get(i).unwrap()).from; + new_to = dfs_code_is_min.get_dfs(min_rm_path[i]).from; break; } } @@ -511,34 +476,36 @@ impl GSpan { dfs_code_is_min: &mut DFSCode, graph_is_min: &'a Graph, min_rm_path: &Vec, - max_to_code: &usize, - ) -> (Option>>>, usize) { - let min_label = dfs_code_is_min.get_dfs(0).from_label.clone(); + max_to_code: usize, + ) -> ( + Option>>>, + usize, + ) { + let min_label = dfs_code_is_min.get_dfs(0).from_label; let mut new_from: usize = 0; - let mut root: Option>> = self + let mut root: Option>> = self .generate_e_to_p_map(projected, graph_is_min, |history| { - let last_rm_path_edge = - history.histories.get(*min_rm_path.get(0).unwrap()).unwrap(); - get_forward_pure(graph_is_min, last_rm_path_edge, &min_label, &history) + let last_rm_path_edge = history.histories[min_rm_path[0]]; + get_forward_pure(graph_is_min, last_rm_path_edge, min_label, &history) }); if root.is_some() { - new_from = max_to_code.clone(); + new_from = max_to_code; } else { // min_rm_path 是从大到小的 dfs_vec 索引 for i in 0..min_rm_path.len() { root = self.generate_e_to_p_map(projected, graph_is_min, |history| { - let cur_rm_path_edge = - history.histories.get(*min_rm_path.get(i).unwrap()).unwrap(); - get_forward_rm_path(graph_is_min, cur_rm_path_edge, &min_label, &history) + let cur_rm_path_edge = history.histories[min_rm_path[i]]; + get_forward_rm_path(graph_is_min, cur_rm_path_edge, min_label, &history) }); if root.is_some() { - new_from = dfs_code_is_min.get_dfs(*min_rm_path.get(i).unwrap()).from; + new_from = dfs_code_is_min.get_dfs(min_rm_path[i]).from; break; } } } + (root, new_from) } @@ -559,8 +526,8 @@ impl GSpan { // 获取最尾边重点到当前边起点的反向边 let backward_edge = get_backward( graph_is_min, - history.histories.get(*min_rm_path.get(i).unwrap()).unwrap(), // 路径当前边 - history.histories.get(*min_rm_path.get(0).unwrap()).unwrap(), // 路径最尾边 + history.histories[min_rm_path[i]], // 路径当前边 + history.histories[min_rm_path[0]], // 路径最尾边 &history, ); if let Some(backward_edge) = backward_edge { @@ -578,12 +545,12 @@ impl GSpan { projected: &'a Projected, graph_is_min: &'a Graph, generate_edges: F, - ) -> Option>>> + ) -> Option>>> where F: Fn(&History) -> Vec<&'a Edge>, { // [e_label][to_label] -> Projected - let mut root: BTreeMap> = BTreeMap::new(); + let mut root: BTreeMap> = BTreeMap::new(); for cur in projected.projections.iter() { let history: History = History::build(cur); @@ -592,8 +559,8 @@ impl GSpan { for it in edges { let key_1 = it.e_label.clone(); let root_1 = root.entry(key_1).or_default(); - let key_2 = graph_is_min.vertex_name_label_map.get(&it.to).unwrap(); - let root_2 = root_1.entry(key_2.clone()).or_insert(Projected::new()); + let key_2 = graph_is_min.key_opkey[it.to]; + let root_2 = root_1.entry(key_2).or_insert(Projected::new()); root_2.push(0, it, Some(cur)); } } @@ -603,12 +570,16 @@ impl GSpan { fn get_first_entry_of_e_to_p<'a>( &self, - root: &'a BTreeMap>, - ) -> (&'a str, &'a str, &'a Projected<'a>) { + root: &'a BTreeMap>, + ) -> (&'a str, usize, &'a Projected<'a>) { let e_label_map_entry = root.first_key_value().unwrap(); let e_label_map_value = e_label_map_entry.1; let to_label_map_entry = e_label_map_value.first_key_value().unwrap(); let to_label_map_value = to_label_map_entry.1; - (e_label_map_entry.0, to_label_map_entry.0, to_label_map_value) + ( + e_label_map_entry.0, + *to_label_map_entry.0, + to_label_map_value, + ) } } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/misc.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/misc.rs index c05071b3306d96962a49b5a3be4cb00784cebf45..156a4b052ec8facaf3e32b575f9714d47d60904d 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/misc.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/misc.rs @@ -34,15 +34,21 @@ pub fn inner_support(projected: &Projected) -> (usize, usize) { let mut unify_vertices_list: Vec> = vec![]; for cur in projected.projections.iter() { - let set: FxHashSet = - cur.get_vertex_names().iter().map(|f| format!("{}/{}", &f.0, &f.1).into()).collect(); + let set: FxHashSet = cur + .get_vertex_names() + .iter() + .map(|f| format!("{}/{}", &f.0, &f.1).into()) + .collect(); // 如果存在 if unify_vertices_list.contains(&set) { continue; } unify_vertices_list.push(set); - count_map.entry(cur.gid).and_modify(|v| *v += 1).or_insert(1); + count_map + .entry(cur.gid) + .and_modify(|v| *v += 1) + .or_insert(1); } let mut min = usize::MAX; @@ -59,7 +65,7 @@ pub fn inner_support(projected: &Projected) -> (usize, usize) { pub fn get_forward_edges<'a>(g: &Graph, v: &'a Vertex) -> Vec<&'a Edge> { let mut result: Vec<&Edge> = Vec::with_capacity(8); for edge in &v.edges { - if v.label <= g.vertex_name_label_map.get(&edge.to).unwrap().clone() { + if v.label <= g.key_opkey[edge.to] { result.push(edge); } } @@ -75,38 +81,35 @@ pub fn get_backward<'a, 'b>( e2: &'a Edge, history: &'b History, ) -> Option<&'a Edge> { - if e1 == e2 { + if *e1 == *e2 { return None; } // 遍历从e2的终点出发的所有边 - for edge in &g.find_vertex(&e2.to).unwrap().edges { + for edge in &g.get_vertex(e2.to)?.edges { if history.has_edge(&edge.id) || edge.to != e1.from { continue; } // 找到一个边的终点是e1的起点 if e1.e_label < edge.e_label || (e1.e_label == edge.e_label - && g.vertex_name_label_map.get(&e1.to).unwrap() - <= g.vertex_name_label_map.get(&e2.to).unwrap()) + && g.key_opkey[&e1.to] + <= g.key_opkey[&e2.to]) { return Some(&edge); } } - return None; + None } -// 获取图中最右下节点引出的所有 Forward 边 pub fn get_forward_pure<'a, 'b>( g: &'a Graph, e: &'b Edge, - min_label: &str, + min_label: usize, history: &'b History, ) -> Vec<&'a Edge> { let mut result: Vec<&Edge> = Vec::with_capacity(8); - for edge in &g.find_vertex(&e.to).unwrap().edges { - if min_label > g.vertex_name_label_map.get(&edge.to).unwrap().as_str() - || history.has_vertex(&edge.to) - { + for edge in &g.get_vertex(e.to).unwrap().edges { + if min_label > g.key_opkey[&edge.to] || history.has_vertex(&edge.to) { continue; } result.push(&edge); @@ -118,14 +121,14 @@ pub fn get_forward_pure<'a, 'b>( pub fn get_forward_rm_path<'a, 'b>( g: &'a Graph, e: &'b Edge, - min_label: &str, + min_label: usize, history: &'b History, ) -> Vec<&'a Edge> { let mut result: Vec<&Edge> = Vec::with_capacity(8); - let to_label = g.vertex_name_label_map.get(&e.to).unwrap().as_str(); + let to_label = g.key_opkey[&e.to]; - for edge in &g.find_vertex(&e.from).unwrap().edges { - let to_label_2 = g.vertex_name_label_map.get(&edge.to).unwrap().as_str(); + for edge in &g.get_vertex(e.from).unwrap().edges { + let to_label_2 = g.key_opkey[&edge.to]; if e.to == edge.to || min_label > to_label_2 || history.has_vertex(&edge.to) { continue; } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs.rs index eac379db002b66ccaa4fa7303159081c115591a8..4881f75370d44acaaa1628352fc11901f21cfb0b 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs.rs @@ -11,18 +11,18 @@ use smartstring::alias::String; pub struct DFS { pub from: usize, pub to: usize, - pub from_label: String, + pub from_label: usize, pub e_label: String, - pub to_label: String, + pub to_label: usize, } impl DFS { pub fn from( from: usize, to: usize, - from_label: String, + from_label: usize, e_label: String, - to_label: String, + to_label: usize, ) -> DFS { DFS { from, to, from_label, e_label, to_label } } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs_code.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs_code.rs index 673dbf136b34b6e1f941ce1a2679926e0c5f2b99..26dad76e4706d46c8f96716f6118f00b65ad2420 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs_code.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/dfs_code.rs @@ -1,9 +1,8 @@ /* * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ -use std::collections::HashSet; -use std::fmt::format; use smartstring::alias::String; +use std::collections::HashSet; use super::projected::Projected; use crate::gspan::{ @@ -24,19 +23,23 @@ pub struct DFSCode { impl DFSCode { pub fn new() -> DFSCode { - DFSCode { is_push_result: false, dfs_vec: Vec::with_capacity(32) } + DFSCode { + is_push_result: false, + dfs_vec: Vec::with_capacity(32), + } } pub fn push( &mut self, from: usize, to: usize, - from_label: String, + from_label: usize, e_label: String, - to_label: String, + to_label: usize, ) { self.is_push_result = false; - self.dfs_vec.push(DFS::from(from, to, from_label, e_label, to_label)); + self.dfs_vec + .push(DFS::from(from, to, from_label, e_label, to_label)); } pub fn pop_with_set_result( @@ -46,10 +49,10 @@ impl DFSCode { ) -> Option { if !self.is_push_result { // 记录尽可能远的深度搜索的结果 - + self.is_push_result = result.add_value(self, projected); } - return self.dfs_vec.pop(); + self.dfs_vec.pop() } pub fn get_dfs(&self, index: usize) -> &DFS { @@ -58,19 +61,17 @@ impl DFSCode { pub fn to_graph(&self, graph_id: usize, directed: bool) -> Graph { let mut g = Graph::new(graph_id, directed); - let mut edge_data = Vec::<(String, String, Option)>::with_capacity(8); + let mut edge_data = Vec::<(usize, usize, Option)>::with_capacity(8); for it in &self.dfs_vec { - let from_name = String::from(format!("{}", it.from)); - if it.from_label != "" && !g.vertex_name_label_map.contains_key(&from_name) { - g.insert_vertex(&from_name, &it.from_label); + if it.from_label != usize::MAX && !g.key_opkey.contains_key(&it.from) { + g.insert_vertex(it.from, it.from_label); } - let to_name = String::from(format!("{}", it.to)); - if it.to_label != "" && !g.vertex_name_label_map.contains_key(&to_name) { - g.insert_vertex(&to_name, &it.to_label); + if it.to_label != usize::MAX && !g.key_opkey.contains_key(&it.to) { + g.insert_vertex(it.to, it.to_label); } // build_edge - edge_data.push((from_name, to_name, Some(it.e_label.clone()))); + edge_data.push((it.from, it.to, Some(it.e_label.clone()))); } g.build_edge(edge_data); g @@ -82,7 +83,7 @@ impl DFSCode { let mut rm_path: Vec = Vec::new(); let mut old_from = usize::MAX; for i in (0..self.dfs_vec.len()).rev() { - let dfs = self.dfs_vec.get(i).unwrap(); + let dfs = &self.dfs_vec[i]; if dfs.from < dfs.to && (rm_path.is_empty() || old_from == dfs.to) { rm_path.push(i); old_from = dfs.from; diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/edge.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/edge.rs index 5d6d483b16a11e38e1227eabcc16ae278f8123f4..1bdf52ed6e474410a64732c72d7440f954a2474e 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/edge.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/edge.rs @@ -4,13 +4,13 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use smartstring::alias::String; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct Edge { pub id: usize, - pub from: String, - pub to: String, - pub from_label: String, - pub to_label: String, + pub from: usize, + pub to: usize, + pub from_label: usize, + pub to_label: usize, pub e_label: String, } @@ -18,10 +18,10 @@ impl Edge { pub const NIL_E_LABEL: &'static str = ""; pub fn new( - from: String, - to: String, - from_label: String, - to_label: String, + from: usize, + to: usize, + from_label: usize, + to_label: usize, e_label: Option, ) -> Edge { static COUNTER: AtomicUsize = AtomicUsize::new(1); @@ -38,11 +38,3 @@ impl Edge { } } } - -impl PartialEq for Edge { - fn eq(&self, other: &Self) -> bool { - self.from_label == other.from_label - && self.to_label == other.to_label - && self.e_label == other.e_label - } -} diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/graph.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/graph.rs index c396933d2aea2be7ec66350eb3090507ab56e265..f82291fdece83877be58d70c5107e2874fdb00a2 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/graph.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/graph.rs @@ -3,13 +3,11 @@ */ use std::collections::HashMap; +use crate::Context; +use crate::gspan::models::{edge::Edge, vertex::Vertex}; +use parser::Model; use smartstring::alias::String; -use crate::{ - gspan::models::{edge::Edge, vertex::Vertex}, - io::{model_graph::ModelGraph, node::Node}, -}; - #[derive(Debug, Clone)] pub struct Graph { pub id: usize, @@ -17,7 +15,7 @@ pub struct Graph { pub edge_size: usize, pub directed: bool, pub vertices: Vec, - pub vertex_name_label_map: HashMap, + pub key_opkey: HashMap, } impl Graph { @@ -28,54 +26,53 @@ impl Graph { edge_size: 0, directed, vertices: Vec::with_capacity(32), - vertex_name_label_map: HashMap::new(), + key_opkey: HashMap::new(), } } - pub fn insert_vertex(&mut self, name: &str, label: &str) { - self.vertex_name_label_map.insert(name.into(), label.into()); - let vertex = Vertex::new(name.into(), Some(label.into())); + pub fn insert_vertex(&mut self, name: usize, label: usize) { + self.key_opkey.insert(name, label); + let vertex = Vertex::new(name, label); self.vertices.push(vertex); } - pub fn build_edge(&mut self, data: Vec<(String, String, Option)>) { + pub fn build_edge(&mut self, data: Vec<(usize, usize, Option)>) { for (from, to, e_label) in data { if let Some(f_vertex) = self.vertices.iter_mut().find(|x| x.name == from) { - if let Some(to_label) = self.vertex_name_label_map.get(&to) { + if let Some(to_label) = self.key_opkey.get(&to) { let edge = Edge::new(from, to, f_vertex.label.clone(), to_label.clone(), e_label); f_vertex.push(edge); self.edge_size += 1; - } else { - println!("Error: build_edge => {} 不存在 to_label.", to); } - } else { - println!("Error: build_edge => {} 不存在 vertex.", from); } } } } impl Graph { - pub fn find_vertex(&self, name: &str) -> Option<&Vertex> { + pub fn get_vertex(&self, name: usize) -> Option<&Vertex> { self.vertices.iter().find(|x| x.name == name) } - fn push_node(&mut self, node: &Node) { - let vertex = Vertex::from(node); - self.vertex_name_label_map.insert(vertex.name.clone(), vertex.label.clone()); + fn get_vertex_mut(&mut self, name: usize) -> Option<&mut Vertex> { + self.vertices.iter_mut().find(|x| x.name == name) + } + + fn add_vertex(&mut self, name: usize, optype: usize) { + let vertex = Vertex::new(name, optype); self.vertices.push(vertex); } - fn build_edges_for_nodes(&mut self, edges: Vec<(String, String)>) { + fn build_edges(&mut self, edges: &Vec<(String, String)>, ctx: &Context) { for (from, to) in edges { - if let Some(f_vertex) = self.vertices.iter_mut().find(|x| x.name == from) { - if let Some(to_label) = self.vertex_name_label_map.get(&to) { + if let Some(f_vertex) = self.get_vertex_mut(ctx.name_key[from.as_str()]) { + if let Some(&to_label) = ctx.name_opkey.get(to.as_str()) { let edge = Edge::new( - from, - to, - f_vertex.label.clone(), - to_label.clone(), + ctx.name_key[from.as_str()], + ctx.name_key[to.as_str()], + f_vertex.label, + to_label, Some(Edge::NIL_E_LABEL.into()), ); f_vertex.push(edge); @@ -87,14 +84,17 @@ impl Graph { } impl Graph { - pub fn from_model_graph(model_graph: ModelGraph, directed: bool) -> Graph { - let node_map = model_graph.nodes; + pub fn from_model_graph(raw: &Model, ctx: &mut Context, directed: bool) -> Graph { let mut graph = Graph::new(0, directed); - graph.name = model_graph.name; - for (_, val) in &node_map { - graph.push_node(val); + graph.name = raw.name.clone(); + for (id, val) in &raw.nodes { + let key = ctx.name_key[id.as_str()]; + let opkey = ctx.op_opkey[val.opType.as_str()]; + graph.key_opkey.insert(key, opkey); + graph.add_vertex(key, opkey); } - graph.build_edges_for_nodes(model_graph.edges); - return graph; + graph.build_edges(&raw.edges, ctx); + + graph } } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/history.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/history.rs index c022dbaebdfdc04ee473947a93c6bb2bd0a18c50..2c577d91246511dcab8577ed8ba36f6e15ee84cf 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/history.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/history.rs @@ -2,7 +2,6 @@ * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ use rustc_hash::FxHashSet; -use smartstring::alias::String; use crate::gspan::models::{edge::Edge, prev_dfs::PrevDFS}; @@ -14,7 +13,7 @@ use crate::gspan::models::{edge::Edge, prev_dfs::PrevDFS}; pub struct History<'a> { pub histories: Vec<&'a Edge>, pub edges: FxHashSet, - pub vertices: FxHashSet, + pub vertices: FxHashSet, } impl<'a> History<'a> { @@ -28,8 +27,8 @@ impl<'a> History<'a> { loop { history.histories.push(e.edge); history.edges.insert(e.edge.id); - history.vertices.insert(e.edge.from.clone()); - history.vertices.insert(e.edge.to.clone()); + history.vertices.insert(e.edge.from); + history.vertices.insert(e.edge.to); if e.prev.is_none() { break; } @@ -43,7 +42,7 @@ impl<'a> History<'a> { self.edges.contains(&id) } - pub fn has_vertex(&self, name: &str) -> bool { + pub fn has_vertex(&self, name: &usize) -> bool { self.vertices.contains(name) } } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/prev_dfs.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/prev_dfs.rs index 3f0d1031c644f31db9ae6fb2505f8fe3a1e5e263..bec4c64efef7bc287c8c000e709ee91e04ded802 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/prev_dfs.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/prev_dfs.rs @@ -2,7 +2,6 @@ * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ use rustc_hash::FxHashSet; -use smartstring::alias::String; use crate::gspan::models::edge::Edge; @@ -34,14 +33,14 @@ impl<'a> PrevDFS<'a> { } } - pub fn get_vertex_names(&self) -> FxHashSet<(usize, String)> { - let mut names: FxHashSet<(usize, String)> = FxHashSet::default(); + pub fn get_vertex_names(&self) -> FxHashSet<(usize, usize)> { + let mut names: FxHashSet<(usize, usize)> = FxHashSet::default(); let mut cur = self; loop { - names.insert((cur.gid.clone(), cur.edge.from.clone())); - names.insert((cur.gid.clone(), cur.edge.to.clone())); + names.insert((cur.gid.clone(), cur.edge.from)); + names.insert((cur.gid.clone(), cur.edge.to)); if let Some(prev) = &cur.prev { cur = **prev; diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/projected.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/projected.rs index 76674aa72c3399cbfa5b56c413be449293edb58b..7a5116a7ca649e68d60ca4660b0452d889f68417 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/projected.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/projected.rs @@ -2,7 +2,6 @@ * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ use rustc_hash::FxHashSet; -use smartstring::alias::String; use crate::gspan::models::{edge::Edge, prev_dfs::PrevDFS}; // PrevDFS 链表节点的集合 @@ -27,7 +26,7 @@ impl<'a> Projected<'a> { self.projections.push(Box::new(new_pdfs)); } - pub fn to_vertex_names_list(&self) -> Vec> { + pub fn to_vertex_names_list(&self) -> Vec> { self.projections.iter().map(|p| p.get_vertex_names()).collect() } diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/vertex.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/vertex.rs index e633757ce04ab8f7a9cc889ac4729c10c4a22c47..6b732f7fd5469bbbf00470a9593c4aa1dd07318f 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/vertex.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/models/vertex.rs @@ -1,26 +1,23 @@ /* * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ -use crate::{gspan::models::edge::Edge, io::node::Node}; -use smartstring::alias::String; +use std::marker::PointeeSized; +use crate::gspan::models::edge::Edge; #[derive(Debug, Clone)] pub struct Vertex { - pub name: String, - pub label: String, + pub name: usize, + pub label: usize, pub edges: Vec, } impl Vertex { - pub const NIL_V_LABEL: &str = ""; + pub const NIL_V_LABEL: usize = usize::MAX; - pub fn new(name: String, label: Option) -> Vertex { + pub fn new(name: usize, label: usize) -> Vertex { Vertex { name, - label: match label { - None => String::new(), - Some(label) => label, - }, + label, edges: Vec::with_capacity(8), } } @@ -28,12 +25,10 @@ impl Vertex { pub fn push(&mut self, edge: Edge) { self.edges.push(edge); } - - pub fn from(node: &Node) -> Vertex { - Vertex::new(node.name.clone(), Some(node.opType.clone())) - } } +impl PointeeSized for Vertex {} + impl PartialEq for Vertex { fn eq(&self, other: &Self) -> bool { self.label == other.label diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/result.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/result.rs index d2c33e7d62ea1e242280f7cd9aa661b2113d912c..b02a5dc0264c1c24bcd1a9aa1cdc576d410ac195 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/result.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/gspan/result.rs @@ -30,7 +30,7 @@ pub struct MaxDFSCodeGraphResult { inner_min_sup: usize, max_pat_min: usize, // Minimum number of vertices max_pat_max: usize, // Maximum number of vertices - value: Vec<(DFSCode, Vec>)>, + value: Vec<(DFSCode, Vec>)>, } impl MaxDFSCodeGraphResult { @@ -66,7 +66,6 @@ impl MaxDFSCodeGraphResult { return false; } let item = (dfs_code.clone(), projected.to_vertex_names_list()); - let edges_list = projected.to_edges_list(); self.value.push(item); true @@ -81,7 +80,7 @@ impl MaxDFSCodeGraphResult { if let Some(graph_id) = first.iter().next().map(|(gid, _)| *gid) { let g = v.0.to_graph(graph_id, false); optype_struct = g.vertices.iter() - .map(|v| v.label.clone()).collect::>().join(",").into(); + .map(|v| v.label.clone()).collect::>().join(",").into(); } } let instances = diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/mod.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/mod.rs index 07c96e70a866a16b7a2470d530018d7c28b45d12..7c23ea701416f627df3c256ac8b36e24ce895a3b 100644 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/mod.rs +++ b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/mod.rs @@ -1,6 +1,4 @@ /* * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. */ -pub mod model_graph; -pub mod node; pub mod output; diff --git a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/node.rs b/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/node.rs deleted file mode 100644 index 9cce1cc429f0183bcda2043a36341ff05db6fad5..0000000000000000000000000000000000000000 --- a/plugins/mindstudio-insight-plugins/ModelVis/rust/subgraph/src/io/node.rs +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved. - */ -use serde::{Deserialize, Serialize}; -use smartstring::alias::String; - -#[derive(Serialize, Deserialize, Debug, Clone)] -#[allow(non_snake_case)] -pub struct Node { - pub name: String, - pub opType: String, - pub input: Vec, -}