use super::{ComputationBudget, LayerMetrics, LayerSkipPattern, ResourceAllocation};
use crate::tensor::Tensor;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::time::{Duration, Instant};
const BRANCH_LAYER_ID_BASE: usize = 9000;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DynamicArchitectureConfig {
pub enable_dynamic_topology: bool,
pub max_concurrent_paths: usize,
pub path_selection_strategy: PathSelectionStrategy,
pub architecture_search_enabled: bool,
pub runtime_modification_enabled: bool,
pub voting_mechanism: VotingMechanism,
pub layer_insertion_threshold: f32,
pub layer_removal_threshold: f32,
pub branching_confidence_threshold: f32,
}
impl Default for DynamicArchitectureConfig {
fn default() -> Self {
Self {
enable_dynamic_topology: true,
max_concurrent_paths: 4,
path_selection_strategy: PathSelectionStrategy::ConfidenceBased,
architecture_search_enabled: false,
runtime_modification_enabled: true,
voting_mechanism: VotingMechanism::WeightedAverage,
layer_insertion_threshold: 0.3,
layer_removal_threshold: 0.8,
branching_confidence_threshold: 0.5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PathSelectionStrategy {
ConfidenceBased,
UncertaintyBased,
EnsembleVoting,
AdaptiveRouting,
CostEffectiveness,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VotingMechanism {
MajorityVote,
WeightedAverage,
ConfidenceWeighted,
UncertaintyWeighted,
ExpertMixing,
}
pub trait PathExecutor: Send + Sync {
fn execute(
&self,
input: &Tensor,
path: &ExecutionPath,
) -> Result<Tensor, Box<dyn std::error::Error>>;
}
pub struct DynamicArchitectureManager {
config: DynamicArchitectureConfig,
#[allow(dead_code)]
active_paths: Arc<RwLock<HashMap<String, ExecutionPath>>>,
#[allow(dead_code)]
architecture_cache: Arc<RwLock<HashMap<String, CachedArchitecture>>>,
performance_history: Arc<RwLock<Vec<ArchitecturePerformance>>>,
topology_modifier: TopologyModifier,
path_router: PathRouter,
path_executor: Option<Arc<dyn PathExecutor>>,
}
impl DynamicArchitectureManager {
pub fn new(config: DynamicArchitectureConfig) -> Self {
Self {
config: config.clone(),
active_paths: Arc::new(RwLock::new(HashMap::new())),
architecture_cache: Arc::new(RwLock::new(HashMap::new())),
performance_history: Arc::new(RwLock::new(Vec::new())),
topology_modifier: TopologyModifier::new(config.clone()),
path_router: PathRouter::new(config.clone()),
path_executor: None,
}
}
pub fn with_path_executor(mut self, executor: Arc<dyn PathExecutor>) -> Self {
self.path_executor = Some(executor);
self
}
pub fn set_path_executor(&mut self, executor: Arc<dyn PathExecutor>) {
self.path_executor = Some(executor);
}
pub fn has_path_executor(&self) -> bool {
self.path_executor.is_some()
}
pub fn create_dynamic_execution_plan(
&self,
input: &Tensor,
base_architecture: &ArchitectureBlueprint,
constraints: &ComputationBudget,
) -> Result<DynamicExecutionPlan, Box<dyn std::error::Error>> {
let input_complexity = self.analyze_input_complexity(input)?;
let execution_paths =
self.generate_execution_paths(input_complexity, base_architecture, constraints)?;
let selected_paths = self.path_router.select_optimal_paths(
&execution_paths,
&self.config.path_selection_strategy,
self.config.max_concurrent_paths,
)?;
Ok(DynamicExecutionPlan {
paths: selected_paths,
voting_mechanism: self.config.voting_mechanism.clone(),
fallback_path: self.create_fallback_path(base_architecture)?,
modification_points: self.identify_modification_points(base_architecture)?,
})
}
pub fn modify_architecture_runtime(
&self,
current_state: &ExecutionState,
performance_metrics: &LayerMetrics,
architecture: &mut ArchitectureBlueprint,
) -> Result<Vec<TopologyModification>, Box<dyn std::error::Error>> {
if !self.config.runtime_modification_enabled {
return Ok(vec![]);
}
let mut modifications = Vec::new();
if performance_metrics.uncertainty_score > self.config.layer_insertion_threshold {
let insertion_point = self
.topology_modifier
.find_optimal_insertion_point(current_state, architecture)?;
if let Some(point) = insertion_point {
let new_layer =
self.topology_modifier.create_adaptive_layer(point, performance_metrics)?;
modifications.push(TopologyModification::InsertLayer {
position: point,
layer_config: new_layer,
});
}
}
if performance_metrics.confidence_score > self.config.layer_removal_threshold {
let removal_candidates =
self.topology_modifier.identify_redundant_layers(current_state, architecture)?;
for candidate in removal_candidates {
modifications.push(TopologyModification::RemoveLayer {
position: candidate,
});
}
}
if self.should_create_branch(performance_metrics) {
let branch_config = self
.topology_modifier
.create_branch_configuration(current_state, performance_metrics)?;
modifications.push(TopologyModification::CreateBranch {
source_position: current_state.current_layer,
branch_config,
});
}
for modification in &modifications {
self.topology_modifier.apply_modification(architecture, modification)?;
}
Ok(modifications)
}
pub fn execute_multi_path(
&self,
input: &Tensor,
execution_plan: &DynamicExecutionPlan,
) -> Result<MultiPathResult, Box<dyn std::error::Error>> {
let start_time = Instant::now();
let mut path_results = Vec::new();
let mut path_metrics = Vec::new();
for (path_id, path) in execution_plan.paths.iter().enumerate() {
let path_start = Instant::now();
let result = self.execute_single_path(input, path)?;
let execution_time = path_start.elapsed();
let metrics = PathExecutionMetrics {
path_id,
execution_time,
confidence: result.confidence,
accuracy_estimate: result.accuracy_estimate,
resource_usage: result.resource_usage.clone(),
};
path_results.push(result);
path_metrics.push(metrics);
}
let final_result = self.combine_path_results(
&path_results,
&path_metrics,
&execution_plan.voting_mechanism,
)?;
self.record_multi_path_performance(&path_metrics, &final_result);
Ok(MultiPathResult {
result: final_result,
path_metrics,
total_execution_time: start_time.elapsed(),
paths_executed: path_results.len(),
})
}
fn analyze_input_complexity(&self, input: &Tensor) -> Result<f32, Box<dyn std::error::Error>> {
let entropy = self.compute_entropy(input)?;
let variance = self.compute_variance(input)?;
let sparsity = self.compute_sparsity(input)?;
let complexity = (entropy * 0.4 + variance * 0.3 + (1.0 - sparsity) * 0.3).clamp(0.0, 1.0);
Ok(complexity)
}
fn generate_execution_paths(
&self,
complexity: f32,
architecture: &ArchitectureBlueprint,
constraints: &ComputationBudget,
) -> Result<Vec<ExecutionPath>, Box<dyn std::error::Error>> {
let mut paths = Vec::new();
let conservative_path = ExecutionPath {
path_id: "conservative".to_string(),
layers: self.select_essential_layers(architecture)?,
skip_patterns: HashMap::new(),
resource_allocation: self.allocate_resources_conservatively(constraints)?,
expected_accuracy: 0.9,
expected_latency: Duration::from_millis(50),
};
paths.push(conservative_path);
let aggressive_path = ExecutionPath {
path_id: "aggressive".to_string(),
layers: architecture.layers.clone(),
skip_patterns: HashMap::new(),
resource_allocation: self.allocate_resources_aggressively(constraints)?,
expected_accuracy: 0.95,
expected_latency: Duration::from_millis(200),
};
paths.push(aggressive_path);
let adaptive_layers = self.select_adaptive_layers(architecture, complexity)?;
let adaptive_path = ExecutionPath {
path_id: "adaptive".to_string(),
layers: adaptive_layers,
skip_patterns: self.generate_skip_patterns(complexity)?,
resource_allocation: self.allocate_resources_adaptively(constraints, complexity)?,
expected_accuracy: 0.85 + complexity * 0.1,
expected_latency: Duration::from_millis((100.0 + complexity * 100.0) as u64),
};
paths.push(adaptive_path);
let efficient_path = ExecutionPath {
path_id: "efficient".to_string(),
layers: self.select_efficient_layers(architecture)?,
skip_patterns: self.generate_efficiency_skip_patterns()?,
resource_allocation: self.allocate_resources_efficiently(constraints)?,
expected_accuracy: 0.8,
expected_latency: Duration::from_millis(30),
};
paths.push(efficient_path);
Ok(paths)
}
fn should_create_branch(&self, metrics: &LayerMetrics) -> bool {
metrics.uncertainty_score > self.config.branching_confidence_threshold
&& metrics.confidence_score < 0.8 }
fn execute_single_path(
&self,
input: &Tensor,
path: &ExecutionPath,
) -> Result<PathResult, Box<dyn std::error::Error>> {
let executor =
self.path_executor.as_ref().ok_or_else(|| -> Box<dyn std::error::Error> {
format!(
"cannot execute path '{}': no PathExecutor is wired up. Call \
DynamicArchitectureManager::with_path_executor with the layer stack that \
should run the path.",
path.path_id
)
.into()
})?;
let start = Instant::now();
let output = executor.execute(input, path)?;
let elapsed = start.elapsed();
let confidence = Self::output_confidence(&output)?;
let memory_mb = (output.size_bytes() / (1024 * 1024)).max(1) as u32;
let flops = output.shape().iter().product::<usize>() as u64;
Ok(PathResult {
output,
confidence,
accuracy_estimate: path.expected_accuracy,
resource_usage: ResourceUsage {
memory_mb,
flops,
time_ms: elapsed.as_millis() as u32,
},
})
}
fn output_confidence(output: &Tensor) -> Result<f32, Box<dyn std::error::Error>> {
let values = output.data()?;
if values.len() < 2 {
return Ok(0.0);
}
let max_value = values.iter().copied().fold(f32::NEG_INFINITY, f32::max);
let exponentials: Vec<f32> = values.iter().map(|value| (value - max_value).exp()).collect();
let sum: f32 = exponentials.iter().sum();
if sum <= 0.0 || !sum.is_finite() {
return Ok(0.0);
}
let mut entropy = 0.0f32;
for exponential in &exponentials {
let probability = exponential / sum;
if probability > 1e-12 {
entropy -= probability * probability.ln();
}
}
let max_entropy = (values.len() as f32).ln();
Ok((1.0 - entropy / max_entropy).clamp(0.0, 1.0))
}
fn combine_path_results(
&self,
results: &[PathResult],
metrics: &[PathExecutionMetrics],
voting_mechanism: &VotingMechanism,
) -> Result<CombinedResult, Box<dyn std::error::Error>> {
match voting_mechanism {
VotingMechanism::WeightedAverage => {
let total_confidence: f32 = metrics.iter().map(|m| m.confidence).sum();
let mut weighted_output = Tensor::zeros_like(&results[0].output)?;
for (result, metric) in results.iter().zip(metrics.iter()) {
let weight = metric.confidence / total_confidence;
let scaled_output = result.output.mul_scalar(weight)?;
weighted_output = weighted_output.add(&scaled_output)?;
}
Ok(CombinedResult {
output: weighted_output,
confidence: total_confidence / results.len() as f32,
consensus_score: self.calculate_consensus_score(metrics),
})
},
VotingMechanism::MajorityVote => {
let best_idx = metrics
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| {
a.confidence
.partial_cmp(&b.confidence)
.unwrap_or(::std::cmp::Ordering::Equal)
})
.map(|(idx, _)| idx)
.unwrap_or(0);
Ok(CombinedResult {
output: results[best_idx].output.clone(),
confidence: metrics[best_idx].confidence,
consensus_score: self.calculate_consensus_score(metrics),
})
},
_ => {
self.combine_path_results(results, metrics, &VotingMechanism::WeightedAverage)
},
}
}
fn calculate_consensus_score(&self, metrics: &[PathExecutionMetrics]) -> f32 {
if metrics.len() < 2 {
return 1.0;
}
let mean_confidence: f32 =
metrics.iter().map(|m| m.confidence).sum::<f32>() / metrics.len() as f32;
let variance =
metrics.iter().map(|m| (m.confidence - mean_confidence).powi(2)).sum::<f32>()
/ metrics.len() as f32;
(1.0 - variance.sqrt()).clamp(0.0, 1.0)
}
fn record_multi_path_performance(
&self,
path_metrics: &[PathExecutionMetrics],
result: &CombinedResult,
) {
let performance = ArchitecturePerformance {
timestamp: Instant::now(),
path_count: path_metrics.len(),
average_confidence: path_metrics.iter().map(|m| m.confidence).sum::<f32>()
/ path_metrics.len() as f32,
consensus_score: result.consensus_score,
total_resource_usage: path_metrics.iter().map(|m| m.resource_usage.memory_mb).sum(),
};
if let Ok(mut history) = self.performance_history.write() {
history.push(performance);
if history.len() > 1000 {
let drain_count = history.len() - 1000;
history.drain(0..drain_count);
}
}
}
fn select_essential_layers(
&self,
arch: &ArchitectureBlueprint,
) -> Result<Vec<LayerConfig>, Box<dyn std::error::Error>> {
Ok(arch.layers.iter().take(arch.layers.len() / 2).cloned().collect())
}
fn select_adaptive_layers(
&self,
arch: &ArchitectureBlueprint,
complexity: f32,
) -> Result<Vec<LayerConfig>, Box<dyn std::error::Error>> {
let layer_count =
((arch.layers.len() as f32 * (0.5 + complexity * 0.5)) as usize).min(arch.layers.len());
Ok(arch.layers.iter().take(layer_count).cloned().collect())
}
fn select_efficient_layers(
&self,
arch: &ArchitectureBlueprint,
) -> Result<Vec<LayerConfig>, Box<dyn std::error::Error>> {
Ok(arch.layers.iter().step_by(2).cloned().collect())
}
fn generate_skip_patterns(
&self,
complexity: f32,
) -> Result<HashMap<usize, LayerSkipPattern>, Box<dyn std::error::Error>> {
let mut patterns = HashMap::new();
if complexity < 0.3 {
for i in (1..10).step_by(2) {
patterns.insert(i, LayerSkipPattern::Skip);
}
}
Ok(patterns)
}
fn generate_efficiency_skip_patterns(
&self,
) -> Result<HashMap<usize, LayerSkipPattern>, Box<dyn std::error::Error>> {
let mut patterns = HashMap::new();
for i in 2..10 {
if i % 3 == 0 {
patterns.insert(i, LayerSkipPattern::Approximate);
}
}
Ok(patterns)
}
fn allocate_resources_conservatively(
&self,
budget: &ComputationBudget,
) -> Result<ResourceAllocation, Box<dyn std::error::Error>> {
Ok(ResourceAllocation {
memory_per_layer: (0..5).map(|i| (i, budget.max_memory_mb / 10)).collect(),
compute_intensity: (0..5).map(|i| (i, 0.5)).collect(),
parallelism_factor: (0..5).map(|i| (i, 1)).collect(),
})
}
fn allocate_resources_aggressively(
&self,
budget: &ComputationBudget,
) -> Result<ResourceAllocation, Box<dyn std::error::Error>> {
Ok(ResourceAllocation {
memory_per_layer: (0..10).map(|i| (i, budget.max_memory_mb / 5)).collect(),
compute_intensity: (0..10).map(|i| (i, 1.0)).collect(),
parallelism_factor: (0..10).map(|i| (i, 2)).collect(),
})
}
fn allocate_resources_adaptively(
&self,
budget: &ComputationBudget,
complexity: f32,
) -> Result<ResourceAllocation, Box<dyn std::error::Error>> {
let layer_count = (8.0 * (0.5 + complexity * 0.5)) as usize;
Ok(ResourceAllocation {
memory_per_layer: (0..layer_count)
.map(|i| {
(
i,
(budget.max_memory_mb as f32 * (0.5 + complexity * 0.5)) as u32
/ layer_count as u32,
)
})
.collect(),
compute_intensity: (0..layer_count).map(|i| (i, 0.5 + complexity * 0.5)).collect(),
parallelism_factor: (0..layer_count)
.map(|i| (i, 1 + (complexity * 2.0) as u32))
.collect(),
})
}
fn allocate_resources_efficiently(
&self,
budget: &ComputationBudget,
) -> Result<ResourceAllocation, Box<dyn std::error::Error>> {
Ok(ResourceAllocation {
memory_per_layer: (0..3).map(|i| (i, budget.max_memory_mb / 20)).collect(),
compute_intensity: (0..3).map(|i| (i, 0.3)).collect(),
parallelism_factor: (0..3).map(|i| (i, 4)).collect(),
})
}
fn create_fallback_path(
&self,
arch: &ArchitectureBlueprint,
) -> Result<ExecutionPath, Box<dyn std::error::Error>> {
Ok(ExecutionPath {
path_id: "fallback".to_string(),
layers: vec![arch.layers[0].clone()], skip_patterns: HashMap::new(),
resource_allocation: ResourceAllocation {
memory_per_layer: HashMap::from([(0, 50)]),
compute_intensity: HashMap::from([(0, 0.1)]),
parallelism_factor: HashMap::from([(0, 1)]),
},
expected_accuracy: 0.6,
expected_latency: Duration::from_millis(10),
})
}
fn identify_modification_points(
&self,
arch: &ArchitectureBlueprint,
) -> Result<Vec<ModificationPoint>, Box<dyn std::error::Error>> {
let mut points = Vec::new();
for i in 0..arch.layers.len() - 1 {
points.push(ModificationPoint {
position: i,
modification_type: ModificationType::LayerInsertion,
confidence_threshold: 0.3,
});
}
for &fraction in &[0.25, 0.5, 0.75] {
let position = (arch.layers.len() as f32 * fraction) as usize;
points.push(ModificationPoint {
position,
modification_type: ModificationType::BranchingPoint,
confidence_threshold: 0.5,
});
}
Ok(points)
}
fn compute_entropy(&self, tensor: &Tensor) -> Result<f32, Box<dyn std::error::Error>> {
Ok(tensor.softmax_entropy_normalized()?)
}
fn compute_variance(&self, tensor: &Tensor) -> Result<f32, Box<dyn std::error::Error>> {
let var = tensor.variance(None, false)?;
Ok(var.to_vec_f32()?.first().copied().unwrap_or(0.0))
}
fn compute_sparsity(&self, tensor: &Tensor) -> Result<f32, Box<dyn std::error::Error>> {
Ok(tensor.sparsity()?)
}
}
#[derive(Debug, Clone)]
pub struct ArchitectureBlueprint {
pub layers: Vec<LayerConfig>,
pub connections: Vec<ConnectionConfig>,
pub metadata: ArchitectureMetadata,
}
#[derive(Debug, Clone)]
pub struct LayerConfig {
pub layer_id: usize,
pub layer_type: LayerType,
pub parameters: HashMap<String, f32>,
pub optional: bool,
}
#[derive(Debug, Clone)]
pub enum LayerType {
Attention,
FeedForward,
Normalization,
Embedding,
Output,
Custom(String),
}
#[derive(Debug, Clone)]
pub struct ConnectionConfig {
pub from_layer: usize,
pub to_layer: usize,
pub connection_type: ConnectionType,
}
#[derive(Debug, Clone)]
pub enum ConnectionType {
Sequential,
Residual,
Attention,
Custom(String),
}
#[derive(Debug, Clone)]
pub struct ArchitectureMetadata {
pub name: String,
pub version: String,
pub parameter_count: u64,
pub memory_footprint_mb: u32,
}
#[derive(Debug, Clone)]
pub struct ExecutionPath {
pub path_id: String,
pub layers: Vec<LayerConfig>,
pub skip_patterns: HashMap<usize, LayerSkipPattern>,
pub resource_allocation: ResourceAllocation,
pub expected_accuracy: f32,
pub expected_latency: Duration,
}
#[derive(Debug)]
pub struct DynamicExecutionPlan {
pub paths: Vec<ExecutionPath>,
pub voting_mechanism: VotingMechanism,
pub fallback_path: ExecutionPath,
pub modification_points: Vec<ModificationPoint>,
}
#[derive(Debug)]
pub struct ExecutionState {
pub current_layer: usize,
pub intermediate_results: HashMap<usize, Tensor>,
pub execution_metrics: Vec<LayerMetrics>,
pub resource_usage: ResourceUsage,
}
#[derive(Debug, Clone)]
pub struct ResourceUsage {
pub memory_mb: u32,
pub flops: u64,
pub time_ms: u32,
}
#[derive(Debug)]
pub enum TopologyModification {
InsertLayer {
position: usize,
layer_config: LayerConfig,
},
RemoveLayer {
position: usize,
},
CreateBranch {
source_position: usize,
branch_config: BranchConfig,
},
ModifyConnection {
connection: ConnectionConfig,
},
}
#[derive(Debug, Clone)]
pub struct BranchConfig {
pub branch_layers: Vec<LayerConfig>,
pub merge_strategy: MergeStrategy,
pub condition: BranchCondition,
}
#[derive(Debug, Clone)]
pub enum MergeStrategy {
Concatenation,
Average,
WeightedSum,
Attention,
}
#[derive(Debug, Clone)]
pub enum BranchCondition {
Always,
ConfidenceThreshold(f32),
UncertaintyThreshold(f32),
Custom(String),
}
#[derive(Debug)]
pub struct ModificationPoint {
pub position: usize,
pub modification_type: ModificationType,
pub confidence_threshold: f32,
}
#[derive(Debug)]
pub enum ModificationType {
LayerInsertion,
LayerRemoval,
BranchingPoint,
ConnectionModification,
}
#[derive(Debug)]
pub struct TopologyModifier {
#[allow(dead_code)]
config: DynamicArchitectureConfig,
}
impl TopologyModifier {
pub fn new(config: DynamicArchitectureConfig) -> Self {
Self { config }
}
pub fn find_optimal_insertion_point(
&self,
state: &ExecutionState,
architecture: &ArchitectureBlueprint,
) -> Result<Option<usize>, Box<dyn std::error::Error>> {
if state.current_layer > 0 && state.current_layer < architecture.layers.len() {
Ok(Some(state.current_layer))
} else {
Ok(None)
}
}
pub fn create_adaptive_layer(
&self,
position: usize,
metrics: &LayerMetrics,
) -> Result<LayerConfig, Box<dyn std::error::Error>> {
let layer_type = if metrics.uncertainty_score > 0.7 {
LayerType::Attention } else {
LayerType::FeedForward };
Ok(LayerConfig {
layer_id: position * 1000, layer_type,
parameters: HashMap::from([
("hidden_size".to_string(), 512.0),
("dropout".to_string(), 0.1),
]),
optional: true,
})
}
pub fn identify_redundant_layers(
&self,
state: &ExecutionState,
architecture: &ArchitectureBlueprint,
) -> Result<Vec<usize>, Box<dyn std::error::Error>> {
let mut redundant = Vec::new();
for (i, layer) in architecture.layers.iter().enumerate() {
if layer.optional
&& state.execution_metrics.get(i).is_some_and(|m| m.confidence_score > 0.9)
{
redundant.push(i);
}
}
Ok(redundant)
}
pub fn create_branch_configuration(
&self,
state: &ExecutionState,
metrics: &LayerMetrics,
) -> Result<BranchConfig, Box<dyn std::error::Error>> {
let branch_layers = vec![LayerConfig {
layer_id: BRANCH_LAYER_ID_BASE + state.current_layer,
layer_type: LayerType::Attention,
parameters: HashMap::from([("heads".to_string(), 8.0)]),
optional: true,
}];
Ok(BranchConfig {
branch_layers,
merge_strategy: MergeStrategy::WeightedSum,
condition: BranchCondition::UncertaintyThreshold(metrics.uncertainty_score),
})
}
pub fn apply_modification(
&self,
architecture: &mut ArchitectureBlueprint,
modification: &TopologyModification,
) -> Result<(), Box<dyn std::error::Error>> {
match modification {
TopologyModification::InsertLayer {
position,
layer_config,
} => {
if *position <= architecture.layers.len() {
architecture.layers.insert(*position, layer_config.clone());
}
},
TopologyModification::RemoveLayer { position } => {
if *position < architecture.layers.len() {
architecture.layers.remove(*position);
}
},
TopologyModification::CreateBranch {
source_position,
branch_config,
} => {
for (i, layer) in branch_config.branch_layers.iter().enumerate() {
architecture.layers.insert(source_position + i + 1, layer.clone());
}
},
TopologyModification::ModifyConnection { connection } => {
architecture.connections.push(connection.clone());
},
}
Ok(())
}
}
#[derive(Debug)]
pub struct PathRouter {
#[allow(dead_code)]
config: DynamicArchitectureConfig,
}
impl PathRouter {
pub fn new(config: DynamicArchitectureConfig) -> Self {
Self { config }
}
pub fn select_optimal_paths(
&self,
paths: &[ExecutionPath],
strategy: &PathSelectionStrategy,
max_paths: usize,
) -> Result<Vec<ExecutionPath>, Box<dyn std::error::Error>> {
let mut selected = match strategy {
PathSelectionStrategy::ConfidenceBased => {
let mut sorted_paths = paths.to_vec();
sorted_paths.sort_by(|a, b| {
b.expected_accuracy
.partial_cmp(&a.expected_accuracy)
.unwrap_or(::std::cmp::Ordering::Equal)
});
sorted_paths
},
PathSelectionStrategy::CostEffectiveness => {
let mut sorted_paths = paths.to_vec();
sorted_paths.sort_by(|a, b| {
let cost_a = a.expected_latency.as_millis() as f32 / a.expected_accuracy;
let cost_b = b.expected_latency.as_millis() as f32 / b.expected_accuracy;
cost_a.partial_cmp(&cost_b).unwrap_or(::std::cmp::Ordering::Equal)
});
sorted_paths
},
_ => paths.to_vec(),
};
selected.truncate(max_paths);
Ok(selected)
}
}
#[derive(Debug)]
pub struct PathResult {
pub output: Tensor,
pub confidence: f32,
pub accuracy_estimate: f32,
pub resource_usage: ResourceUsage,
}
#[derive(Debug)]
pub struct PathExecutionMetrics {
pub path_id: usize,
pub execution_time: Duration,
pub confidence: f32,
pub accuracy_estimate: f32,
pub resource_usage: ResourceUsage,
}
#[derive(Debug)]
pub struct CombinedResult {
pub output: Tensor,
pub confidence: f32,
pub consensus_score: f32,
}
#[derive(Debug)]
pub struct MultiPathResult {
pub result: CombinedResult,
pub path_metrics: Vec<PathExecutionMetrics>,
pub total_execution_time: Duration,
pub paths_executed: usize,
}
#[derive(Debug)]
pub struct ArchitecturePerformance {
pub timestamp: Instant,
pub path_count: usize,
pub average_confidence: f32,
pub consensus_score: f32,
pub total_resource_usage: u32,
}
#[derive(Debug)]
pub struct CachedArchitecture {
pub blueprint: ArchitectureBlueprint,
pub performance_history: Vec<ArchitecturePerformance>,
pub last_used: Instant,
}