Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions src/approximation/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use crate::core::exceptions::GraphinaException;
use crate::core::paths::dijkstra;
use crate::core::types::{BaseGraph, GraphConstructor, NodeId};
use crate::core::types::{BaseGraph, EdgeType, NodeId};
use ordered_float::OrderedFloat;
use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
Expand All @@ -23,7 +23,7 @@ fn find_path<A, Ty>(
blocked: &HashSet<NodeId>,
) -> Option<Vec<NodeId>>
where
Ty: crate::core::types::GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut prev: Vec<Option<NodeId>> = vec![None; n];
Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn local_node_connectivity<A, Ty>(
target: NodeId,
) -> usize
where
Ty: GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType,
{
let mut connectivity = 0;
let mut blocked = HashSet::new();
Expand All @@ -80,7 +80,7 @@ where
/// Approximate a maximum independent set using a greedy algorithm with neighbor caching.
pub fn maximum_independent_set<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> HashSet<NodeId>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut mis = HashSet::new();
let mut nodes: Vec<NodeId> = graph.nodes().map(|(u, _)| u).collect();
Expand All @@ -107,7 +107,7 @@ where
/// Approximate a maximum clique using a greedy heuristic with neighbor caching.
pub fn max_clique<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> HashSet<NodeId>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut best = HashSet::new();
let neighbor_cache: HashMap<NodeId, HashSet<NodeId>> = graph
Expand Down Expand Up @@ -139,7 +139,7 @@ where
/// Repeatedly remove a clique (found via max_clique) from the graph until no nodes remain.
pub fn clique_removal<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> Vec<HashSet<NodeId>>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut cliques = Vec::new();
let mut remaining: HashSet<NodeId> = graph.nodes().map(|(u, _)| u).collect();
Expand All @@ -163,7 +163,7 @@ where
/// Return the size of a large clique approximated by the max_clique heuristic.
pub fn large_clique_size<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> usize
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
max_clique(graph).len()
}
Expand All @@ -172,7 +172,7 @@ where
/// Estimate the average clustering coefficient using cached neighbor sets.
pub fn average_clustering<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> f64
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut total = 0.0;
let mut count = 0;
Expand Down Expand Up @@ -214,7 +214,7 @@ pub fn densest_subgraph<A, Ty>(
_iterations: Option<usize>,
) -> HashSet<NodeId>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut best_density = 0.0;
let mut best_set = HashSet::new();
Expand Down Expand Up @@ -273,7 +273,7 @@ pub fn diameter<A, Ty>(
graph: &BaseGraph<A, OrderedFloat<f64>, Ty>,
) -> Result<f64, GraphinaException>
where
Ty: GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType,
{
if let Some((start, _)) = graph.nodes().next() {
let distances = dijkstra(graph, start)?;
Expand Down Expand Up @@ -305,7 +305,7 @@ pub fn min_weighted_vertex_cover<A, Ty>(
_weight: Option<&dyn Fn(NodeId) -> f64>,
) -> std::collections::HashSet<NodeId>
where
Ty: crate::core::types::GraphConstructor<A, f64>,
Ty: crate::core::types::EdgeType,
{
let mut cover = HashSet::new();
let mut uncovered: HashSet<(NodeId, NodeId)> = graph.edges().map(|(u, v, _)| (u, v)).collect();
Expand Down Expand Up @@ -336,7 +336,7 @@ where
/// Approximate the minimum maximal matching using a greedy algorithm.
pub fn min_maximal_matching<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> HashSet<(NodeId, NodeId)>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut matching = HashSet::new();
let mut matched = HashSet::new();
Expand All @@ -354,7 +354,7 @@ where
/// Approximate Ramsey R2 by computing a maximum clique and a maximum independent set.
pub fn ramsey_r2<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> (HashSet<NodeId>, HashSet<NodeId>)
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let clique = max_clique(graph);
let independent_set = maximum_independent_set(graph);
Expand All @@ -368,7 +368,7 @@ pub fn christofides<A, Ty>(
) -> Result<(Vec<NodeId>, f64), GraphinaException>
where
A: Clone,
Ty: GraphConstructor<A, f64> + GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType + EdgeType,
{
let start_node = graph
.nodes()
Expand All @@ -385,7 +385,7 @@ pub fn traveling_salesman_problem<A, Ty>(
) -> Result<(Vec<NodeId>, f64), GraphinaException>
where
A: Clone,
Ty: GraphConstructor<A, f64> + GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType + EdgeType,
{
let start_node = graph
.nodes()
Expand All @@ -403,7 +403,7 @@ pub fn greedy_tsp<A, Ty>(
source: NodeId,
) -> Result<(Vec<NodeId>, f64), GraphinaException>
where
Ty: GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType,
{
let mut unvisited: HashSet<NodeId> = graph.nodes().map(|(u, _)| u).collect();
let mut tour = Vec::new();
Expand Down Expand Up @@ -441,7 +441,7 @@ pub fn simulated_annealing_tsp<A, Ty>(
) -> Result<(Vec<NodeId>, f64), GraphinaException>
where
A: Clone,
Ty: GraphConstructor<A, f64> + GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType + EdgeType,
{
let cost = tour_cost(&graph.convert::<OrderedFloat<f64>>(), &init_cycle)?;
Ok((init_cycle, cost))
Expand All @@ -455,7 +455,7 @@ pub fn threshold_accepting_tsp<A, Ty>(
) -> Result<(Vec<NodeId>, f64), GraphinaException>
where
A: Clone,
Ty: GraphConstructor<A, f64> + GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType + EdgeType,
{
let cost = tour_cost(&graph.convert::<OrderedFloat<f64>>(), &init_cycle)?;
Ok((init_cycle, cost))
Expand All @@ -465,7 +465,7 @@ where
/// Asadpour ATSP (not implemented).
pub fn asadpour_atsp<A, Ty>(_graph: &BaseGraph<A, f64, Ty>) -> (Vec<NodeId>, f64)
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
unimplemented!("Asadpour ATSP algorithm is not implemented yet")
}
Expand All @@ -477,7 +477,7 @@ fn tour_cost<A, Ty>(
tour: &[NodeId],
) -> Result<f64, GraphinaException>
where
Ty: GraphConstructor<A, OrderedFloat<f64>>,
Ty: EdgeType,
{
let mut cost = 0.0;
for i in 0..tour.len() - 1 {
Expand All @@ -493,7 +493,7 @@ where
/// Compute a treewidth decomposition using the Minimum Degree heuristic with a min-heap.
pub fn treewidth_min_degree<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> (usize, Vec<NodeId>)
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut order = Vec::new();
let mut remaining: HashSet<NodeId> = graph.nodes().map(|(u, _)| u).collect();
Expand Down Expand Up @@ -533,7 +533,7 @@ where
/// Compute a treewidth decomposition using the Minimum Fill-in heuristic.
pub fn treewidth_min_fill_in<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> (usize, Vec<NodeId>)
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let mut order = Vec::new();
let mut remaining: HashSet<NodeId> = graph.nodes().map(|(u, _)| u).collect();
Expand Down
48 changes: 24 additions & 24 deletions src/centrality/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

use crate::core::exceptions::GraphinaException;
use crate::core::paths::dijkstra;
use crate::core::types::{BaseGraph, GraphConstructor, NodeId};
use crate::core::types::{BaseGraph, EdgeType, NodeId};
use std::collections::{HashMap, VecDeque};

//
Expand All @@ -28,9 +28,9 @@ use std::collections::{HashMap, VecDeque};
pub fn degree_centrality<A, W, Ty>(graph: &BaseGraph<A, W, Ty>) -> Vec<f64>
where
W: Copy,
Ty: GraphConstructor<A, W>,
Ty: EdgeType,
{
if !<Ty as GraphConstructor<A, W>>::is_directed() {
if !Ty::is_directed() {
return out_degree_centrality(graph);
}
let n = graph.node_count();
Expand All @@ -48,9 +48,9 @@ where
pub fn in_degree_centrality<A, W, Ty>(graph: &BaseGraph<A, W, Ty>) -> Vec<f64>
where
W: Copy,
Ty: GraphConstructor<A, W>,
Ty: EdgeType,
{
if !<Ty as GraphConstructor<A, W>>::is_directed() {
if !Ty::is_directed() {
return out_degree_centrality(graph);
}
let n = graph.node_count();
Expand All @@ -65,7 +65,7 @@ where
pub fn out_degree_centrality<A, W, Ty>(graph: &BaseGraph<A, W, Ty>) -> Vec<f64>
where
W: Copy,
Ty: GraphConstructor<A, W>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut cent = vec![0.0; n];
Expand All @@ -88,7 +88,7 @@ pub fn eigenvector_centrality_impl<A, Ty>(
tol: f64,
) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut centrality = vec![1.0; n];
Expand Down Expand Up @@ -121,7 +121,7 @@ where
/// Wrapper for eigenvector centrality with default tolerance (1e-6).
pub fn eigenvector_centrality<A, Ty>(graph: &BaseGraph<A, f64, Ty>, max_iter: usize) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
eigenvector_centrality_impl(graph, max_iter, 1e-6_f64)
}
Expand All @@ -133,7 +133,7 @@ pub fn eigenvector_centrality_numpy<A, Ty>(
tol: f64,
) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
eigenvector_centrality_impl(graph, max_iter, tol)
}
Expand All @@ -154,7 +154,7 @@ pub fn katz_centrality_impl<A, Ty>(
tol: f64,
) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut centrality = vec![beta; n];
Expand Down Expand Up @@ -193,7 +193,7 @@ pub fn katz_centrality<A, Ty>(
max_iter: usize,
) -> Vec<f64>
where
Ty: crate::core::types::GraphConstructor<A, f64>,
Ty: crate::core::types::EdgeType,
{
katz_centrality_impl(graph, alpha, beta, max_iter, 1e-6_f64)
}
Expand All @@ -205,7 +205,7 @@ pub fn katz_centrality_numpy<A, Ty>(
beta: f64,
) -> Vec<f64>
where
Ty: crate::core::types::GraphConstructor<A, f64>,
Ty: crate::core::types::EdgeType,
{
katz_centrality_impl(graph, alpha, beta, 100, 1e-6_f64)
}
Expand All @@ -222,7 +222,7 @@ pub fn closeness_centrality<A, Ty>(
graph: &BaseGraph<A, ordered_float::OrderedFloat<f64>, Ty>,
) -> Result<Vec<f64>, GraphinaException>
where
Ty: GraphConstructor<A, ordered_float::OrderedFloat<f64>>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut closeness = vec![0.0; n];
Expand Down Expand Up @@ -250,7 +250,7 @@ pub fn pagerank_impl<A, Ty>(
tol: f64,
) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut rank = vec![1.0 / n as f64; n];
Expand Down Expand Up @@ -293,7 +293,7 @@ where
/// This wrapper takes 3 arguments: graph, damping, max_iter.
pub fn pagerank<A, Ty>(graph: &BaseGraph<A, f64, Ty>, damping: f64, max_iter: usize) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
pagerank_impl(graph, damping, max_iter, 1e-6_f64)
}
Expand All @@ -307,7 +307,7 @@ where
/// Compute betweenness centrality (node version) using Brandes’ algorithm.
pub fn betweenness_centrality<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut bc = vec![0.0; n];
Expand Down Expand Up @@ -356,7 +356,7 @@ pub fn edge_betweenness_centrality<A, Ty>(
graph: &BaseGraph<A, f64, Ty>,
) -> HashMap<(usize, usize), f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut eb: HashMap<(usize, usize), f64> = HashMap::new();
Expand Down Expand Up @@ -414,7 +414,7 @@ pub fn harmonic_centrality<A, Ty>(
graph: &BaseGraph<A, ordered_float::OrderedFloat<f64>, Ty>,
) -> Result<Vec<f64>, GraphinaException>
where
Ty: GraphConstructor<A, ordered_float::OrderedFloat<f64>>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut centrality = vec![0.0; n];
Expand All @@ -440,7 +440,7 @@ where
/// Local reaching centrality: fraction of nodes reachable from a given node (via BFS).
pub fn local_reaching_centrality<A, Ty>(graph: &BaseGraph<A, f64, Ty>, v: NodeId) -> f64
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut visited = vec![false; n];
Expand All @@ -467,7 +467,7 @@ where
/// Global reaching centrality: average difference between the maximum local reaching centrality and each node’s value.
pub fn global_reaching_centrality<A, Ty>(graph: &BaseGraph<A, f64, Ty>) -> f64
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let lrc: Vec<f64> = graph
.nodes()
Expand All @@ -488,7 +488,7 @@ where
/// Initial scores are the nodes’ out–degrees; after selection, the scores of their neighbors are reduced.
pub fn voterank<A, Ty>(graph: &BaseGraph<A, f64, Ty>, number_of_nodes: usize) -> Vec<NodeId>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
let n = graph.node_count();
let mut scores = vec![0.0; n];
Expand All @@ -504,9 +504,9 @@ where
.filter(|(i, _)| !voted[*i])
.max_by(|a, b| a.1.partial_cmp(b.1).unwrap_or(std::cmp::Ordering::Equal))
.unwrap();
selected.push(NodeId::new(petgraph::graph::NodeIndex::new(max_idx)));
selected.push(petgraph::graph::NodeIndex::new(max_idx));
voted[max_idx] = true;
for nb in graph.neighbors(NodeId::new(petgraph::graph::NodeIndex::new(max_idx))) {
for nb in graph.neighbors(petgraph::graph::NodeIndex::new(max_idx)) {
scores[nb.index()] *= 0.8;
}
}
Expand All @@ -523,7 +523,7 @@ where
/// Here LC(v) = d(v)^2 + 2 * (sum of 1’s for each neighbor).
pub fn laplacian_centrality<A, Ty>(graph: &BaseGraph<A, f64, Ty>, _normalized: bool) -> Vec<f64>
where
Ty: GraphConstructor<A, f64>,
Ty: EdgeType,
{
graph
.nodes()
Expand Down
Loading
Loading