Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Algorithm standardisation #1896

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
17 changes: 9 additions & 8 deletions python/python/raphtory/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ConstProperties(object):
"""A view of constant properties of an entity"""

def __contains__(self, key):
"""Return key in self."""
"""Return bool(key in self)."""

def __eq__(self, value):
"""Return self==value."""
Expand Down Expand Up @@ -220,11 +220,12 @@ class DiskGraphStorage(object):
def load_from_parquets(
graph_dir,
layer_parquet_cols,
node_properties,
chunk_size,
t_props_chunk_size,
num_threads,
node_type_col,
node_properties=None,
chunk_size=10000000,
t_props_chunk_size=10000000,
num_threads=4,
node_type_col=None,
node_id_col=None,
): ...
def load_node_const_properties(self, location, col_names=None, chunk_size=None): ...
def merge_by_sorted_gids(self, other, graph_dir):
Expand Down Expand Up @@ -4498,7 +4499,7 @@ class Properties(object):
"""A view of the properties of an entity"""

def __contains__(self, key):
"""Return key in self."""
"""Return bool(key in self)."""

def __eq__(self, value):
"""Return self==value."""
Expand Down Expand Up @@ -4685,7 +4686,7 @@ class TemporalProperties(object):
"""A view of the temporal properties of an entity"""

def __contains__(self, key):
"""Return key in self."""
"""Return bool(key in self)."""

def __eq__(self, value):
"""Return self==value."""
Expand Down
46 changes: 31 additions & 15 deletions python/python/raphtory/algorithms/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Matching(object):
"""True if self else False"""

def __contains__(self, key):
"""Return key in self."""
"""Return bool(key in self)."""

def __iter__(self):
"""Implement iter(self)."""
Expand Down Expand Up @@ -159,9 +159,26 @@ def betweenness_centrality(
"""

def cohesive_fruchterman_reingold(
graph, iterations=100, scale=1.0, node_start_size=1.0, cooloff_factor=0.95, dt=0.1
g: GraphView,
iter_count: int = 100,
scale: float = 1.0,
node_start_size: float = 1.0,
cooloff_factor: float = 0.95,
dt: float = 0.1,
):
"""Cohesive version of `fruchterman_reingold` that adds virtual edges between isolated nodes"""
"""
Arguments:
g (GraphView): A reference to the graph
iter_count (int): The number of iterations to run
scale (float): Global scaling factor to control the overall spread of the graph
node_start_size (float): Initial size or movement range for nodes
cooloff_factor (float): Factor to reduce node movement in later iterations, helping stabilize the layout
dt (float): Time step or movement factor in each iteration

Returns:
An [AlgorithmResult] containing a mapping between vertices and a pair of coordinates.
wyatt-joyner-pometry marked this conversation as resolved.
Show resolved Hide resolved

"""

def connected_components(g): ...
def degree_centrality(g: GraphView, threads: Optional[int] = None) -> AlgorithmResult:
Expand Down Expand Up @@ -291,7 +308,7 @@ def global_reciprocity(g: GraphView):
float : reciprocity of the graph between 0 and 1.
"""

def global_temporal_three_node_motif(g: GraphView, delta: int):
def global_temporal_three_node_motif(g: GraphView, delta: int, threads=None):
"""
Computes the number of three edge, up-to-three node delta-temporal motifs in the graph, using the algorithm of Paranjape et al, Motifs in Temporal Networks (2017).
We point the reader to this reference for more information on the algorithm and background, but provide a short summary below.
Expand Down Expand Up @@ -339,7 +356,9 @@ def global_temporal_three_node_motif(g: GraphView, delta: int):

"""

def global_temporal_three_node_motif_multi(g: GraphView, deltas: list[int]):
def global_temporal_three_node_motif_multi(
g: GraphView, deltas: list[int], threads=None
):
"""
Computes the global counts of three-edge up-to-three node temporal motifs for a range of timescales. See `global_temporal_three_node_motif` for an interpretation of each row returned.

Expand Down Expand Up @@ -418,7 +437,7 @@ def local_clustering_coefficient(g: GraphView, v: InputNode):
float : the local clustering coefficient of node v in g.
"""

def local_temporal_three_node_motifs(g: GraphView, delta: int):
def local_temporal_three_node_motifs(g: GraphView, delta: int, threads=None):
"""
Computes the number of each type of motif that each node participates in. See global_temporal_three_node_motifs for a summary of the motifs involved.

Expand Down Expand Up @@ -454,17 +473,14 @@ def local_triangle_count(g: GraphView, v: InputNode):
"""

def louvain(
graph: GraphView,
resolution: float = 1.0,
weight_prop: str | None = None,
tol: None | float = None,
g, resolution: float = 1.0, weight_prop: str | None = None, tol: None | float = None
wyatt-joyner-pometry marked this conversation as resolved.
Show resolved Hide resolved
):
"""
Louvain algorithm for community detection

Arguments:
graph (GraphView): the graph view
resolution (float): the resolution paramter for modularity
resolution (float): the resolution parameter for modularity
weight_prop (str | None): the edge property to use for weights (has to be float)
tol (None | float): the floating point tolerance for deciding if improvements are significant (default: 1e-8)
"""
Expand Down Expand Up @@ -503,7 +519,7 @@ def max_out_degree(g: GraphView):
"""

def max_weight_matching(
graph: GraphView,
g,
weight_prop: Optional[str] = None,
max_cardinality: bool = True,
verify_optimum_flag: bool = False,
Expand Down Expand Up @@ -652,7 +668,7 @@ def strongly_connected_components(g: GraphView):
"""

def temporal_SEIR(
graph: GraphView,
g,
seeds: int | float | list[InputNode],
infection_prob: float,
initial_infection: int | str | datetime,
Expand Down Expand Up @@ -693,7 +709,7 @@ def temporal_SEIR(
"""

def temporal_bipartite_graph_projection(
g: GraphView, delta: int, pivot_type
g: GraphView, delta: int, pivot_type: str
) -> GraphView:
"""
Projects a temporal bipartite graph into an undirected temporal graph over the pivot node type. Let G be a bipartite graph with node types A and B. Given delta > 0, the projection graph G' pivoting over type B nodes,
Expand All @@ -702,7 +718,7 @@ def temporal_bipartite_graph_projection(
Arguments:
g (GraphView) : A directed raphtory graph
delta (int): Time period
pivot (str) : node type to pivot over. If a bipartite graph has types A and B, and B is the pivot type, the new graph will consist of type A nodes.
pivot_type (str) : node type to pivot over. If a bipartite graph has types A and B, and B is the pivot type, the new graph will consist of type A nodes.

Returns:
GraphView: Projected (unipartite) temporal graph.
Expand Down
21 changes: 16 additions & 5 deletions raphtory-graphql/src/model/algorithms/algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ use dynamic_graphql::{internal::TypeName, SimpleObject};
use futures_util::future::BoxFuture;
use itertools::Itertools;
use ordered_float::OrderedFloat;
use raphtory::algorithms::{
centrality::pagerank::unweighted_page_rank,
pathing::dijkstra::dijkstra_single_source_shortest_paths,
use raphtory::{
algorithms::{
centrality::pagerank::unweighted_page_rank,
pathing::dijkstra::dijkstra_single_source_shortest_paths,
},
core::Prop,
};
use raphtory_api::core::Direction;
use std::collections::HashMap;

#[derive(SimpleObject)]
pub(crate) struct PagerankOutput {
Expand Down Expand Up @@ -160,8 +164,15 @@ fn apply_shortest_path<'b>(
.iter()
.map(|v| v.string())
.collect::<Result<Vec<&str>, _>>()?;
let binding =
dijkstra_single_source_shortest_paths(&entry_point.graph, source, targets, None, direction);
let binding: Result<HashMap<String, (f64, Vec<String>)>, &str> =
Ok(dijkstra_single_source_shortest_paths(
&entry_point.graph,
source,
targets,
None,
direction,
)?
.get_all_with_names());
let result: Vec<FieldValue> = binding
.into_iter()
.flat_map(|pair| {
Expand Down
15 changes: 14 additions & 1 deletion raphtory/src/algorithms/algorithm_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ impl<T: FloatCore> AsOrd<OrderedFloat<T>> for T {
}
}

impl<T: FloatCore> AsOrd<[OrderedFloat<T>; 2]> for [T; 2] {
fn as_ord(&self) -> &[OrderedFloat<T>; 2] {
unsafe { &*(self as *const [T; 2] as *const [OrderedFloat<T>; 2]) }
}
}

impl<T: FloatCore> AsOrd<(OrderedFloat<T>, Vec<String>)> for (T, Vec<String>) {
fn as_ord(&self) -> &(OrderedFloat<T>, Vec<String>) {
unsafe { &*(self as *const (T, Vec<String>) as *const (OrderedFloat<T>, Vec<String>)) }
}
}

impl<T: FloatCore> AsOrd<(OrderedFloat<T>, OrderedFloat<T>)> for (T, T) {
fn as_ord(&self) -> &(OrderedFloat<T>, OrderedFloat<T>) {
// Safety: OrderedFloat is #[repr(transparent)] and has no invalid values, i.e. there is no physical difference between OrderedFloat and Float.
Expand Down Expand Up @@ -377,7 +389,8 @@ use crate::{
prelude::GraphViewOps,
};
use num_traits::float::FloatCore;
use std::fmt;
use std::{fmt, fmt::Display};
wyatt-joyner-pometry marked this conversation as resolved.
Show resolved Hide resolved
// use crate::python::types::repr::Repr;
wyatt-joyner-pometry marked this conversation as resolved.
Show resolved Hide resolved

impl<'graph, G: GraphViewOps<'graph>, V: fmt::Debug, O> fmt::Display for AlgorithmResult<G, V, O> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
12 changes: 8 additions & 4 deletions raphtory/src/algorithms/bipartite/max_weight_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,17 +826,21 @@ fn verify_optimum(
///
/// The function takes time O(n**3)
///
/// Arguments:
/// # Arguments
///
/// * `graph` - The graph to compute the maximum weight matching for
/// * `max_cardinality` - If set to true compute the maximum-cardinality matching
/// - `graph` - The graph to compute the maximum weight matching for
/// - `max_cardinality` - If set to true compute the maximum-cardinality matching
/// with maximum weight among all maximum-cardinality matchings
/// * `verify_optimum_flag`: If true prior to returning an additional routine
/// - `verify_optimum_flag`: If true prior to returning an additional routine
/// to verify the optimal solution was found will be run after computing
/// the maximum weight matching. If it's true and the found matching is not
/// an optimal solution this function will panic. This option should
/// normally be only set true during testing.
///
/// # Returns
///
/// A [Matching] object that contains a mapping of vertices to outwardly and inwardly assigned target vertices.
///
/// # Example
/// ```rust
///
Expand Down
4 changes: 2 additions & 2 deletions raphtory/src/algorithms/centrality/betweenness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use std::collections::{HashMap, VecDeque};

/// Computes the betweenness centrality for nodes in a given graph.
///
/// # Parameters
/// # Arguments
///
/// - `g`: A reference to the graph.
/// - `k`: An `Option<usize>` specifying the number of nodes to consider for the centrality computation. Defaults to all nodes if `None`.
/// - `normalized`: If `true` normalize the centrality values.
///
/// # Returns
///
/// Returns an `AlgorithmResult` containing the betweenness centrality of each node.
/// An [AlgorithmResult] containing the betweenness centrality of each node.
pub fn betweenness_centrality<'graph, G: GraphViewOps<'graph>>(
g: &'graph G,
k: Option<usize>,
Expand Down
9 changes: 9 additions & 0 deletions raphtory/src/algorithms/centrality/degree_centrality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ use ordered_float::OrderedFloat;
/// Computes the degree centrality of all nodes in the graph. The values are normalized
/// by dividing each result with the maximum possible degree. Graphs with self-loops can have
/// values of centrality greater than 1.
///
/// # Arguments
///
/// - `g`: A reference to the graph.
/// - `threads` - Number of threads to use
///
/// # Returns
///
/// An [AlgorithmResult] containing the degree centrality of each node.
pub fn degree_centrality<G: StaticGraphViewOps>(
g: &G,
threads: Option<usize>,
Expand Down
10 changes: 8 additions & 2 deletions raphtory/src/algorithms/centrality/hits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,15 @@ impl Default for Hits {
/// HubScore of a node (A) = Sum of AuthScore of all nodes pointing away from node (A) from previous iteration /
/// Sum of AuthScore of all nodes in the current iteration
///
/// Returns
/// # Arguments
///
/// * An AlgorithmResult object containing the mapping from node ID to the hub and authority score of the node
/// - `g`: A reference to the graph.
/// - `iter_count` - The number of iterations to run
/// - `threads` - Number of threads to use
///
/// # Returns
///
/// An [AlgorithmResult] object containing the mapping from node ID to the hub and authority score of the node
pub fn hits<G: StaticGraphViewOps>(
g: &G,
iter_count: usize,
Expand Down
18 changes: 9 additions & 9 deletions raphtory/src/algorithms/centrality/pagerank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ impl PageRankState {
/// PageRank Algorithm:
/// PageRank shows how important a node is in a graph.
///
/// Arguments:
/// # Arguments
///
/// * `g`: A GraphView object
/// * `iter_count`: Number of iterations to run the algorithm for
/// * `threads`: Number of threads to use for parallel execution
/// * `tol`: The tolerance value for convergence
/// * `use_l2_norm`: Whether to use L2 norm for convergence
/// * `damping_factor`: Probability of likelihood the spread will continue
/// - `g`: A GraphView object
/// - `iter_count`: Number of iterations to run the algorithm for
/// - `threads`: Number of threads to use for parallel execution
/// - `tol`: The tolerance value for convergence
/// - `use_l2_norm`: Whether to use L2 norm for convergence
/// - `damping_factor`: Probability of likelihood the spread will continue
///
/// Result:
/// # Returns
///
/// * An AlgorithmResult object containing the mapping from node ID to the PageRank score of the node
/// An [AlgorithmResult] object containing the mapping from node ID to the PageRank score of the node
///
pub fn unweighted_page_rank<G: StaticGraphViewOps>(
g: &G,
Expand Down
10 changes: 5 additions & 5 deletions raphtory/src/algorithms/community_detection/label_propagation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ use crate::{
///
/// # Arguments
///
/// * `g` - A reference to the graph
/// * `seed` - (Optional) Array of 32 bytes of u8 which is set as the rng seed
/// - `g` - A reference to the graph
/// - `seed` - (Optional) Array of 32 bytes of u8 which is set as the rng seed
///
/// Returns:
/// # Returns
///
/// A vector of hashsets each containing nodes
///
pub fn label_propagation<G>(
graph: &G,
g: &G,
seed: Option<[u8; 32]>,
) -> Result<Vec<HashSet<NodeView<G>>>, &'static str>
where
G: StaticGraphViewOps,
{
let mut labels: HashMap<NodeView<&G>, GID> = HashMap::new();
let nodes = &graph.nodes();
let nodes = &g.nodes();
for node in nodes.iter() {
labels.insert(node, node.id());
}
Expand Down
Loading
Loading