use crate::graph::edge::Edge;
use crate::graph::graph::{Graph, GraphConstructor};
use crate::graph::undirected::edge::UndirectedEdge;
use crate::graph::vertex::Vertex;
use crate::service::component_analysis::edge_pairs::PairsOfNonAdjacentEdges;
use crate::service::component_analysis::vertex_pairs::PairsOfAdjacentVertices;
pub fn dot_product<G: Graph<E = UndirectedEdge> + Clone + GraphConstructor, V: Vertex>(
graph_g: &G,
graph_h: &G,
edge_of_g_first: &UndirectedEdge,
edge_of_g_second: &UndirectedEdge,
vertex_of_h_first: &V,
vertex_of_h_second: &V,
) -> G {
let mut graph_gh = concat_graphs(graph_g, graph_h);
let graph_h_begin_index = graph_g.size();
graph_gh.remove_edge(edge_of_g_first.from(), edge_of_g_first.to());
graph_gh.remove_edge(edge_of_g_second.from(), edge_of_g_second.to());
graph_gh.remove_edges_of_vertex(vertex_of_h_first.index() + graph_h_begin_index);
graph_gh.remove_edges_of_vertex(vertex_of_h_second.index() + graph_h_begin_index);
let mut neighbors_of_first_vertex = vec![];
for neighbor in graph_h.neighbors_of_vertex(vertex_of_h_first.index()) {
if neighbor != vertex_of_h_second.index() {
neighbors_of_first_vertex.push(neighbor);
}
}
let mut neighbors_of_second_vertex = vec![];
for neighbor in graph_h.neighbors_of_vertex(vertex_of_h_second.index()) {
if neighbor != vertex_of_h_first.index() {
neighbors_of_second_vertex.push(neighbor);
}
}
if neighbors_of_first_vertex.len() != 2 || neighbors_of_second_vertex.len() != 2 {
}
graph_gh.add_edge(
edge_of_g_first.from(),
neighbors_of_first_vertex[0] + graph_h_begin_index,
);
graph_gh.add_edge(
edge_of_g_first.to(),
neighbors_of_first_vertex[1] + graph_h_begin_index,
);
graph_gh.add_edge(
edge_of_g_second.from(),
neighbors_of_second_vertex[0] + graph_h_begin_index,
);
graph_gh.add_edge(
edge_of_g_second.to(),
neighbors_of_second_vertex[1] + graph_h_begin_index,
);
wipe_vertices_without_edges(&graph_gh)
}
pub fn concat_graphs<G: Graph + Clone>(first: &G, second: &G) -> G {
let mut result = first.clone();
let second_begin_index = first.size();
for edge in first.edges() {
result.add_edge(edge.from(), edge.to());
}
for edge in second.edges() {
result.add_edge(
second_begin_index + edge.from(),
second_begin_index + edge.to(),
);
}
result
}
pub struct DotProducts<'a, G: Graph<E = UndirectedEdge>> {
graph_g: &'a G,
graph_h: &'a G,
non_adjacent_edge_pairs_of_g: PairsOfNonAdjacentEdges<'a, G>,
adjacent_vertex_pairs_of_h: PairsOfAdjacentVertices<'a, G::V, G>,
edge_pair_current: Option<(&'a UndirectedEdge, &'a UndirectedEdge)>,
}
impl<'a, G: Graph<E = UndirectedEdge> + Clone + GraphConstructor> DotProducts<'a, G> {
pub fn new(graph_g: &'a G, graph_h: &'a G) -> Self {
DotProducts {
graph_g,
graph_h,
non_adjacent_edge_pairs_of_g: PairsOfNonAdjacentEdges::new(graph_g),
adjacent_vertex_pairs_of_h: PairsOfAdjacentVertices::new(graph_h),
edge_pair_current: None,
}
}
}
impl<'a, G: Graph<E = UndirectedEdge> + Clone + GraphConstructor> Iterator for DotProducts<'a, G> {
type Item = G;
fn next(&mut self) -> Option<Self::Item> {
if self.edge_pair_current.is_none() {
self.edge_pair_current = self.non_adjacent_edge_pairs_of_g.next();
}
if let Some(edges) = self.edge_pair_current {
if let Some(vertices) = self.adjacent_vertex_pairs_of_h.next() {
let graph = dot_product(
self.graph_g,
self.graph_h,
edges.0,
edges.1,
vertices.0,
vertices.1,
);
return Some(graph);
}
self.edge_pair_current = None;
self.adjacent_vertex_pairs_of_h = PairsOfAdjacentVertices::new(self.graph_h);
return self.next();
}
None
}
}
fn wipe_vertices_without_edges<G: Graph + GraphConstructor>(graph: &G) -> G {
let mut vertices_without_edges = vec![];
for vertex in graph.vertices() {
if graph.neighbors_of_vertex(vertex.index()).is_empty() {
vertices_without_edges.push(vertex.index());
}
}
let mut removed_vertex_iter = vertices_without_edges.iter();
let mut removed_vertex_next = removed_vertex_iter.next();
let mut index_mapping = vec![0; graph.size()];
let mut counter = 0;
for vertex in graph.vertices() {
if let Some(removed) = removed_vertex_next {
if *removed == vertex.index() {
counter += 1;
removed_vertex_next = removed_vertex_iter.next();
continue;
}
}
index_mapping[vertex.index()] = vertex.index() - counter;
}
let mut final_graph = G::with_vertices_capacity(graph.size() - vertices_without_edges.len());
for edge in graph.edges() {
final_graph.add_edge(index_mapping[edge.from()], index_mapping[edge.to()]);
}
final_graph
}