diff --git a/src/algorithm/bellande_node_importance.rs b/src/algorithm/bellande_node_importance.rs
index 68a0a2d..c6eed34 100644
--- a/src/algorithm/bellande_node_importance.rs
+++ b/src/algorithm/bellande_node_importance.rs
@@ -13,5 +13,292 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-use crate::algorithm::connections::BellandeArchError;
+use crate::algorithm::connections::{euclidean_distance, BellandeArchError};
use bellande_node_importance::make_bellande_node_importance_request;
+use futures::future::join_all;
+use serde::{Deserialize, Serialize};
+use serde_json::Value;
+
+/// Configuration for node importance evaluation using Bellande Node Importance algorithm
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct NodeImportanceConfig {
+ pub node_coordinates: Vec,
+ pub segment_id: String,
+ pub recent_nodes: Vec>,
+ pub important_nodes_by_segment: std::collections::HashMap>>,
+ pub adjacent_segments: std::collections::HashMap>,
+ pub grid_steps: Vec,
+ pub min_segment_coverage: f64,
+ pub use_local_executable: bool,
+}
+
+/// Result of a node importance evaluation operation
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct NodeImportanceResult {
+ pub importance_score: f64,
+ pub coverage_metrics: Option>,
+ pub segment_coverage: Option,
+ pub execution_time_ms: Option,
+ pub node_attributes: Option>,
+}
+
+/// Extended configuration for advanced node importance evaluations
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct AdvancedNodeImportanceConfig {
+ pub basic_config: NodeImportanceConfig,
+ pub priority_regions: Option>>>,
+ pub coverage_bias: Option,
+ pub weighting_factor: Option,
+}
+
+/// Main node importance evaluation module that leverages the Bellande Node Importance algorithm
+pub struct NodeImportanceEvaluator;
+
+impl NodeImportanceEvaluator {
+ /// Evaluates the importance of a node using the Bellande Node Importance algorithm
+ pub async fn evaluate(
+ config: NodeImportanceConfig,
+ ) -> Result {
+ // Validate input coordinates
+ if config.node_coordinates.is_empty() {
+ return Err(BellandeArchError::InvalidCoordinates(
+ "Node coordinates cannot be empty".to_string(),
+ ));
+ }
+
+ // Validate segment ID
+ if config.segment_id.is_empty() {
+ return Err(BellandeArchError::InvalidCoordinates(
+ "Segment ID cannot be empty".to_string(),
+ ));
+ }
+
+ // Validate grid steps
+ if config.grid_steps.is_empty() {
+ return Err(BellandeArchError::InvalidCoordinates(
+ "Grid steps cannot be empty".to_string(),
+ ));
+ }
+
+ let dimensions = config.node_coordinates.len();
+
+ // Verify that grid steps have the same dimensions as node coordinates
+ if dimensions != config.grid_steps.len() {
+ return Err(BellandeArchError::DimensionMismatch(format!(
+ "Coordinate dimension mismatch: node={}, grid_steps={}",
+ dimensions,
+ config.grid_steps.len()
+ )));
+ }
+
+ // Create the node JSON structure
+ let node = serde_json::json!({
+ "coords": config.node_coordinates,
+ "segment": config.segment_id
+ });
+
+ // Convert recent nodes to JSON Value
+ let recent_nodes = serde_json::json!(config.recent_nodes);
+
+ // Convert important nodes to JSON Value
+ let important_nodes = serde_json::json!(config.important_nodes_by_segment);
+
+ // Convert adjacent segments to JSON Value
+ let adjacent_segments = serde_json::json!(config.adjacent_segments);
+
+ // Convert grid steps to JSON Value
+ let grid_steps = serde_json::json!(config.grid_steps);
+
+ // Run the Bellande Node Importance algorithm using the API
+ let result = if !config.use_local_executable {
+ make_bellande_node_importance_request(
+ node,
+ recent_nodes,
+ important_nodes,
+ adjacent_segments,
+ grid_steps,
+ config.min_segment_coverage,
+ )
+ .await
+ .map_err(|e| BellandeArchError::AlgorithmError(e.to_string()))?
+ } else {
+ return Err(BellandeArchError::AlgorithmError(
+ "Local executable functionality not implemented".to_string(),
+ ));
+ };
+
+ // Process and transform the results
+ Self::process_result(result)
+ }
+
+ /// Process the raw Bellande Node Importance result into our domain-specific format
+ pub fn process_result(result: Value) -> Result {
+ // Extract the importance score from the result
+ let importance_score = result
+ .get("importance_score")
+ .and_then(|s| s.as_f64())
+ .ok_or_else(|| {
+ BellandeArchError::AlgorithmError(
+ "Missing importance score in algorithm result".to_string(),
+ )
+ })?;
+
+ // Extract coverage metrics if available
+ let coverage_metrics = result
+ .get("coverage_metrics")
+ .and_then(|m| m.as_array())
+ .map(|metrics| {
+ metrics
+ .iter()
+ .filter_map(|v| v.as_f64())
+ .collect::>()
+ });
+
+ // Extract segment coverage if available
+ let segment_coverage = result.get("segment_coverage").and_then(|c| c.as_f64());
+
+ // Extract execution time if available
+ let execution_time_ms = result
+ .get("execution_time_ms")
+ .and_then(|t| t.as_i64())
+ .map(|t| t as i32);
+
+ // Extract node attributes if available
+ let node_attributes = result
+ .get("node_attributes")
+ .and_then(|a| a.as_object())
+ .map(|obj| {
+ obj.iter()
+ .map(|(k, v)| (k.clone(), v.clone()))
+ .collect::>()
+ });
+
+ Ok(NodeImportanceResult {
+ importance_score,
+ coverage_metrics,
+ segment_coverage,
+ execution_time_ms,
+ node_attributes,
+ })
+ }
+
+ /// Evaluates node importance with optimal parameters based on segment characteristics
+ pub async fn evaluate_optimal(
+ node_coords: Vec,
+ segment_id: String,
+ recent_nodes: Vec>,
+ important_nodes_by_segment: std::collections::HashMap>>,
+ adjacent_segments: std::collections::HashMap>,
+ ) -> Result {
+ // Validate inputs
+ if node_coords.is_empty() || segment_id.is_empty() {
+ return Err(BellandeArchError::InvalidCoordinates(
+ "Node coordinates and segment ID cannot be empty".to_string(),
+ ));
+ }
+
+ let dimensions = node_coords.len();
+
+ // Determine appropriate grid steps based on segment characteristics
+ let grid_steps = if let Some(segment_nodes) = important_nodes_by_segment.get(&segment_id) {
+ if !segment_nodes.is_empty() {
+ // Calculate average distance between nodes in this segment
+ let mut total_distance = 0.0;
+ let mut count = 0;
+
+ for i in 0..segment_nodes.len() {
+ for j in i + 1..segment_nodes.len() {
+ if let Ok(dist) = euclidean_distance(&segment_nodes[i], &segment_nodes[j]) {
+ total_distance += dist;
+ count += 1;
+ }
+ }
+ }
+
+ let avg_distance = if count > 0 {
+ total_distance / count as f64
+ } else {
+ 1.0
+ };
+ // Use 10% of average distance as grid step
+ vec![avg_distance * 0.1; dimensions]
+ } else {
+ // Default grid steps if no nodes in segment
+ vec![1.0; dimensions]
+ }
+ } else {
+ // Default grid steps if segment not found
+ vec![1.0; dimensions]
+ };
+
+ // Determine minimum segment coverage based on adjacent segments count
+ let adjacent_count = adjacent_segments
+ .get(&segment_id)
+ .map(|adj| adj.len())
+ .unwrap_or(0);
+
+ let min_segment_coverage = match adjacent_count {
+ 0 => 0.7, // Isolated segment, require higher coverage
+ 1..=2 => 0.6, // Few connections
+ 3..=5 => 0.5, // Moderate connections
+ _ => 0.4, // Many connections, can be more flexible
+ };
+
+ // Basic configuration
+ let config = NodeImportanceConfig {
+ node_coordinates: node_coords,
+ segment_id,
+ recent_nodes,
+ important_nodes_by_segment,
+ adjacent_segments,
+ grid_steps,
+ min_segment_coverage,
+ use_local_executable: false,
+ };
+
+ // Perform evaluation
+ Self::evaluate(config).await
+ }
+
+ /// Batch processes multiple node importance evaluations in parallel
+ pub async fn batch_evaluate(
+ configs: Vec,
+ ) -> Vec> {
+ // Process each configuration in parallel
+ let futures = configs.into_iter().map(|config| Self::evaluate(config));
+
+ // Collect all results
+ join_all(futures).await
+ }
+
+ /// Advanced batch processing with custom parameters for each evaluation
+ pub async fn advanced_batch_evaluate(
+ configs: Vec,
+ ) -> Vec> {
+ let futures = configs.into_iter().map(|config| {
+ // Use basic evaluation
+ Self::evaluate(config.basic_config)
+ });
+
+ join_all(futures).await
+ }
+
+ /// Calculates a comparative importance score between two nodes
+ pub fn calculate_comparative_importance(
+ node1_result: &NodeImportanceResult,
+ node2_result: &NodeImportanceResult,
+ weighting_factor: f64,
+ ) -> f64 {
+ // Basic comparison of importance scores
+ let importance_diff = node1_result.importance_score - node2_result.importance_score;
+
+ // Consider segment coverage if available
+ let coverage_factor = match (node1_result.segment_coverage, node2_result.segment_coverage) {
+ (Some(cov1), Some(cov2)) => (cov1 - cov2) * weighting_factor,
+ _ => 0.0,
+ };
+
+ // Combined score
+ importance_diff + coverage_factor
+ }
+}
diff --git a/src/algorithm/bellande_step.rs b/src/algorithm/bellande_step.rs
index d36df90..ca286eb 100644
--- a/src/algorithm/bellande_step.rs
+++ b/src/algorithm/bellande_step.rs
@@ -14,8 +14,7 @@
// along with this program. If not, see .
use crate::algorithm::connections::{
- euclidean_distance, is_point_valid, vector_dot_product, vector_length, vector_subtract,
- BellandeArchError,
+ euclidean_distance, vector_dot_product, vector_length, vector_subtract, BellandeArchError,
};
use bellande_step::make_bellande_step_request;
use futures::future::join_all;