use std::{num::NonZeroUsize, ptr};
use cugraph_sys::{cugraph_error_t, cugraph_extract_ego, cugraph_induced_subgraph_result_t, cugraph_k_truss_subgraph};
use crate::{
array::DeviceArrayView,
error::{Error, Result, check_error, require_non_null},
graph::Graph,
handle::EnteredContext,
structure::{
subgraph::InducedSubgraphResult,
typed_results::{IntegerValues, ScoreValues, SizeValues, VertexIds},
},
types::{CugraphElement, to_bool_t},
};
#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct KTrussSubgraphParams {
pub k: NonZeroUsize,
pub do_expensive_check: bool,
}
impl Default for KTrussSubgraphParams {
fn default() -> Self {
Self {
k: unsafe { NonZeroUsize::new_unchecked(3) },
do_expensive_check: false,
}
}
}
#[derive(Debug, Clone, Copy)]
#[must_use]
pub struct ExtractEgoParams {
pub radius: NonZeroUsize,
pub do_expensive_check: bool,
}
impl Default for ExtractEgoParams {
fn default() -> Self {
Self {
radius: unsafe { NonZeroUsize::new_unchecked(1) },
do_expensive_check: false,
}
}
}
pub(crate) fn k_truss_subgraph<T>(
handle: &EnteredContext<'_>,
graph: &mut Graph<T>,
params: &KTrussSubgraphParams,
) -> Result<KTrussSubgraphResult> {
let mut result: *mut cugraph_induced_subgraph_result_t = ptr::null_mut();
let mut error: *mut cugraph_error_t = ptr::null_mut();
let graph_ptr = graph.as_ptr(handle, "k_truss_subgraph")?;
unsafe {
let code = cugraph_k_truss_subgraph(
handle.handle_ptr(),
graph_ptr,
params.k.get(),
to_bool_t(params.do_expensive_check),
&mut result,
&mut error,
);
check_error(code, error, handle.device(), "k_truss_subgraph")?;
}
let result = require_non_null(result, "k_truss_subgraph", "induced_subgraph_result")?;
let inner = unsafe {
InducedSubgraphResult::from_raw(result, handle.device(), "k_truss_subgraph", handle.runtime_bound_lease())
}?;
Ok(KTrussSubgraphResult(inner))
}
pub(crate) fn extract_ego<T, V: CugraphElement>(
handle: &EnteredContext<'_>,
graph: &mut Graph<T>,
source_vertices: &DeviceArrayView<'_, V>,
params: &ExtractEgoParams,
) -> Result<ExtractEgoResult> {
let mut result: *mut cugraph_induced_subgraph_result_t = ptr::null_mut();
let mut error: *mut cugraph_error_t = ptr::null_mut();
let graph_ptr = graph.as_ptr(handle, "extract_ego")?;
unsafe {
let code = cugraph_extract_ego(
handle.handle_ptr(),
graph_ptr,
source_vertices.as_ptr().cast_const(),
params.radius.get(),
to_bool_t(params.do_expensive_check),
&mut result,
&mut error,
);
check_error(code, error, handle.device(), "extract_ego")?;
}
let result = require_non_null(result, "extract_ego", "induced_subgraph_result")?;
let inner = unsafe {
InducedSubgraphResult::from_raw(result, handle.device(), "extract_ego", handle.runtime_bound_lease())
}?;
Ok(ExtractEgoResult(inner))
}
macro_rules! induced_result_accessors {
($ty:ident, $df_fn:ident) => {
impl $ty {
pub fn sources(&self) -> Result<VertexIds<'_>> {
self.0.sources(concat!(stringify!($ty), "::sources"))
}
pub fn destinations(&self) -> Result<VertexIds<'_>> {
self.0.destinations(concat!(stringify!($ty), "::destinations"))
}
pub fn weights(&self) -> Result<Option<ScoreValues<'_>>> {
self.0.weights(concat!(stringify!($ty), "::weights"))
}
pub fn edge_ids(&self) -> Result<Option<IntegerValues<'_>>> {
self.0.edge_ids(concat!(stringify!($ty), "::edge_ids"))
}
pub fn edge_type_ids(&self) -> Result<Option<IntegerValues<'_>>> {
self.0.edge_type_ids(concat!(stringify!($ty), "::edge_type_ids"))
}
pub fn subgraph_offsets(&self) -> Result<Option<SizeValues<'_>>> {
self.0.subgraph_offsets(concat!(stringify!($ty), "::subgraph_offsets"))
}
pub fn to_dataframe(&self, runtime: &cudf::Runtime) -> Result<cudf::DataFrame> {
crate::cudf_interop::$df_fn(self, runtime)
.map_err(|e: Error| e.with_operation(concat!(stringify!($ty), "::to_dataframe")))
}
}
};
}
pub struct KTrussSubgraphResult(InducedSubgraphResult);
impl std::fmt::Debug for KTrussSubgraphResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("KTrussSubgraphResult").finish_non_exhaustive()
}
}
induced_result_accessors!(KTrussSubgraphResult, k_truss_subgraph_result_to_dataframe);
pub struct ExtractEgoResult(InducedSubgraphResult);
impl std::fmt::Debug for ExtractEgoResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ExtractEgoResult").finish_non_exhaustive()
}
}
induced_result_accessors!(ExtractEgoResult, extract_ego_result_to_dataframe);