Buckets:
tostido/Butterfly-Field-Station-storage / work /Convergence_Engine /kernel /trait_convergence_engine.py
| # Trait Convergence Engine - Phase 0.5 Implementation | |
| # Version 1.0 - Mathematical Formula for Trait Inheritance | |
| """ | |
| Trait Convergence Engine implementing the mathematical formula for trait inheritance. | |
| This is the core mechanism that drives evolution through controlled trait convergence. | |
| Core Formula: T_child = (W₁×P₁ + W₂×P₂)/(W₁+W₂) ± ε | |
| Where ε ∈ [-δ, δ] within stability envelope | |
| This engine relies on stability envelopes defined within the trait ontology | |
| and integrates with the violation pressure system for mathematical governance. | |
| """ | |
| import random | |
| import math | |
| import logging | |
| from typing import Dict, List, Tuple, Optional, Any | |
| from dataclasses import dataclass, field | |
| from datetime import datetime | |
| from enum import Enum | |
| logger = logging.getLogger(__name__) | |
| from violation_pressure_calculation import StabilityEnvelope, ViolationMonitor | |
| from event_driven_coordination import DjinnEventBus, EventType, TraitConvergenceRequest | |
| class ConvergenceMethod(Enum): | |
| """Methods for trait convergence""" | |
| WEIGHTED_AVERAGE = "weighted_average" | |
| DOMINANCE_INHERITANCE = "dominance_inheritance" | |
| RANDOM_SELECTION = "random_selection" | |
| STABILITY_OPTIMIZED = "stability_optimized" | |
| class ConvergenceResult: | |
| """Result of trait convergence operation""" | |
| child_traits: Dict[str, float] | |
| convergence_method: ConvergenceMethod | |
| mutation_applied: Dict[str, float] | |
| stability_envelope_compliance: Dict[str, bool] | |
| convergence_pressure: float | |
| timestamp: datetime | |
| parent_uuids: List[str] = field(default_factory=list) | |
| def to_dict(self) -> Dict[str, Any]: | |
| return { | |
| "child_traits": self.child_traits, | |
| "convergence_method": self.convergence_method.value, | |
| "mutation_applied": self.mutation_applied, | |
| "stability_envelope_compliance": self.stability_envelope_compliance, | |
| "convergence_pressure": self.convergence_pressure, | |
| "timestamp": self.timestamp.isoformat() + "Z", | |
| "parent_uuids": self.parent_uuids | |
| } | |
| class TraitConvergenceEngine: | |
| """ | |
| Core engine for trait convergence implementing mathematical inheritance formulas. | |
| This engine: | |
| - Executes trait convergence between parent entities | |
| - Applies controlled mutation within stability envelopes | |
| - Ensures mathematical compliance with VP system | |
| - Integrates with event-driven coordination | |
| """ | |
| def __init__(self, violation_monitor: ViolationMonitor, event_bus: Optional[DjinnEventBus] = None): | |
| self.violation_monitor = violation_monitor | |
| self.event_bus = event_bus | |
| self.convergence_history = [] | |
| # Convergence parameters | |
| self.convergence_parameters = { | |
| "base_mutation_rate": 0.1, # Base mutation magnitude | |
| "stability_compression": 0.8, # Compression factor for stability enforcement | |
| "dominance_threshold": 0.7, # Threshold for dominance inheritance | |
| "random_selection_prob": 0.1 # Probability of random trait selection | |
| } | |
| def converge_traits(self, parent1_traits: Dict[str, float], | |
| parent2_traits: Dict[str, float], | |
| parent1_uuid: str = None, | |
| parent2_uuid: str = None, | |
| method: ConvergenceMethod = ConvergenceMethod.WEIGHTED_AVERAGE) -> ConvergenceResult: | |
| """ | |
| Execute trait convergence between two parent entities. | |
| Args: | |
| parent1_traits: Trait dictionary for first parent | |
| parent2_traits: Trait dictionary for second parent | |
| parent1_uuid: UUID of first parent (optional) | |
| parent2_uuid: UUID of second parent (optional) | |
| method: Convergence method to use | |
| Returns: | |
| ConvergenceResult with child traits and metadata | |
| """ | |
| # Determine convergence method | |
| if method == ConvergenceMethod.WEIGHTED_AVERAGE: | |
| child_traits = self._weighted_average_convergence(parent1_traits, parent2_traits) | |
| elif method == ConvergenceMethod.DOMINANCE_INHERITANCE: | |
| child_traits = self._dominance_inheritance_convergence(parent1_traits, parent2_traits) | |
| elif method == ConvergenceMethod.RANDOM_SELECTION: | |
| child_traits = self._random_selection_convergence(parent1_traits, parent2_traits) | |
| elif method == ConvergenceMethod.STABILITY_OPTIMIZED: | |
| child_traits = self._stability_optimized_convergence(parent1_traits, parent2_traits) | |
| else: | |
| raise ValueError(f"Unknown convergence method: {method}") | |
| # Apply controlled mutation | |
| mutation_applied = self._apply_controlled_mutation(child_traits) | |
| # Check stability envelope compliance | |
| compliance = self._check_stability_compliance(child_traits) | |
| # Calculate convergence pressure | |
| convergence_pressure = self._calculate_convergence_pressure(child_traits) | |
| # Create convergence result | |
| result = ConvergenceResult( | |
| child_traits=child_traits, | |
| convergence_method=method, | |
| mutation_applied=mutation_applied, | |
| stability_envelope_compliance=compliance, | |
| convergence_pressure=convergence_pressure, | |
| timestamp=datetime.utcnow(), | |
| parent_uuids=[parent1_uuid, parent2_uuid] if parent1_uuid and parent2_uuid else [] | |
| ) | |
| # Record in history | |
| self.convergence_history.append(result) | |
| # Publish convergence event if event bus available | |
| if self.event_bus: | |
| self._publish_convergence_event(result) | |
| return result | |
| def _weighted_average_convergence(self, parent1_traits: Dict[str, float], | |
| parent2_traits: Dict[str, float]) -> Dict[str, float]: | |
| """ | |
| Weighted average convergence: T_child = (W₁×P₁ + W₂×P₂)/(W₁+W₂) | |
| This is the standard mathematical formula for trait inheritance. | |
| """ | |
| child_traits = {} | |
| # Get all unique trait names | |
| all_traits = set(parent1_traits.keys()) | set(parent2_traits.keys()) | |
| for trait_name in all_traits: | |
| # Get trait values from parents (default to 0.5 if missing) | |
| p1_value = parent1_traits.get(trait_name, 0.5) | |
| p2_value = parent2_traits.get(trait_name, 0.5) | |
| # Calculate weights based on trait stability | |
| w1 = self._calculate_trait_weight(trait_name, p1_value) | |
| w2 = self._calculate_trait_weight(trait_name, p2_value) | |
| # Apply weighted average formula | |
| if w1 + w2 > 0: | |
| child_value = (w1 * p1_value + w2 * p2_value) / (w1 + w2) | |
| else: | |
| child_value = (p1_value + p2_value) / 2 # Fallback to simple average | |
| # Clamp to [0.0, 1.0] range | |
| child_traits[trait_name] = max(0.0, min(1.0, child_value)) | |
| return child_traits | |
| def _dominance_inheritance_convergence(self, parent1_traits: Dict[str, float], | |
| parent2_traits: Dict[str, float]) -> Dict[str, float]: | |
| """ | |
| Dominance inheritance: Select the more stable trait value for each trait. | |
| """ | |
| child_traits = {} | |
| all_traits = set(parent1_traits.keys()) | set(parent2_traits.keys()) | |
| for trait_name in all_traits: | |
| p1_value = parent1_traits.get(trait_name, 0.5) | |
| p2_value = parent2_traits.get(trait_name, 0.5) | |
| # Calculate stability scores | |
| p1_stability = self._calculate_trait_stability(trait_name, p1_value) | |
| p2_stability = self._calculate_trait_stability(trait_name, p2_value) | |
| # Select the more stable value | |
| if p1_stability > p2_stability: | |
| child_traits[trait_name] = p1_value | |
| else: | |
| child_traits[trait_name] = p2_value | |
| return child_traits | |
| def _random_selection_convergence(self, parent1_traits: Dict[str, float], | |
| parent2_traits: Dict[str, float]) -> Dict[str, float]: | |
| """ | |
| Random selection: Randomly select trait values from parents. | |
| """ | |
| child_traits = {} | |
| all_traits = set(parent1_traits.keys()) | set(parent2_traits.keys()) | |
| for trait_name in all_traits: | |
| p1_value = parent1_traits.get(trait_name, 0.5) | |
| p2_value = parent2_traits.get(trait_name, 0.5) | |
| # Random selection with equal probability | |
| if random.random() < 0.5: | |
| child_traits[trait_name] = p1_value | |
| else: | |
| child_traits[trait_name] = p2_value | |
| return child_traits | |
| def _stability_optimized_convergence(self, parent1_traits: Dict[str, float], | |
| parent2_traits: Dict[str, float]) -> Dict[str, float]: | |
| """ | |
| Stability optimized: Choose values that minimize violation pressure. | |
| """ | |
| child_traits = {} | |
| all_traits = set(parent1_traits.keys()) | set(parent2_traits.keys()) | |
| for trait_name in all_traits: | |
| p1_value = parent1_traits.get(trait_name, 0.5) | |
| p2_value = parent2_traits.get(trait_name, 0.5) | |
| # Calculate VP for each potential value | |
| test_traits = {trait_name: p1_value} | |
| vp1, _ = self.violation_monitor.compute_violation_pressure(test_traits) | |
| test_traits = {trait_name: p2_value} | |
| vp2, _ = self.violation_monitor.compute_violation_pressure(test_traits) | |
| # Choose the value with lower VP | |
| if vp1 < vp2: | |
| child_traits[trait_name] = p1_value | |
| else: | |
| child_traits[trait_name] = p2_value | |
| return child_traits | |
| def _calculate_trait_weight(self, trait_name: str, trait_value: float) -> float: | |
| """ | |
| Calculate weight for trait based on stability envelope. | |
| More stable traits get higher weights. | |
| """ | |
| envelope = self.violation_monitor.get_stability_envelope(trait_name) | |
| if envelope: | |
| # Weight based on distance from stability center | |
| distance = abs(trait_value - envelope.center) | |
| # Closer to center = higher weight | |
| weight = 1.0 - (distance / envelope.radius) | |
| return max(0.1, weight) # Minimum weight of 0.1 | |
| else: | |
| return 1.0 # Default weight | |
| def _calculate_trait_stability(self, trait_name: str, trait_value: float) -> float: | |
| """ | |
| Calculate stability score for trait value. | |
| Higher score = more stable. | |
| """ | |
| envelope = self.violation_monitor.get_stability_envelope(trait_name) | |
| if envelope: | |
| # Calculate distance from stability center | |
| distance = abs(trait_value - envelope.center) | |
| # Stability decreases with distance | |
| stability = 1.0 - (distance / envelope.radius) | |
| return max(0.0, stability) | |
| else: | |
| return 0.5 # Default stability | |
| def _apply_controlled_mutation(self, child_traits: Dict[str, float]) -> Dict[str, float]: | |
| """ | |
| Apply controlled mutation within stability envelopes. | |
| Returns: | |
| Dictionary of mutation amounts applied to each trait | |
| """ | |
| mutations = {} | |
| for trait_name, trait_value in child_traits.items(): | |
| envelope = self.violation_monitor.get_stability_envelope(trait_name) | |
| if envelope: | |
| # Calculate mutation range based on stability envelope | |
| mutation_range = envelope.radius * self.convergence_parameters["base_mutation_rate"] | |
| # Apply compression factor | |
| mutation_range *= self.convergence_parameters["stability_compression"] | |
| # Generate random mutation | |
| mutation = random.uniform(-mutation_range, mutation_range) | |
| # Apply mutation | |
| new_value = trait_value + mutation | |
| # Clamp to [0.0, 1.0] range | |
| child_traits[trait_name] = max(0.0, min(1.0, new_value)) | |
| mutations[trait_name] = mutation | |
| else: | |
| mutations[trait_name] = 0.0 | |
| return mutations | |
| def _check_stability_compliance(self, child_traits: Dict[str, float]) -> Dict[str, bool]: | |
| """ | |
| Check if child traits comply with stability envelopes. | |
| """ | |
| compliance = {} | |
| for trait_name, trait_value in child_traits.items(): | |
| envelope = self.violation_monitor.get_stability_envelope(trait_name) | |
| if envelope: | |
| # Check if value is within stability envelope | |
| distance = abs(trait_value - envelope.center) | |
| compliance[trait_name] = distance <= envelope.radius | |
| else: | |
| compliance[trait_name] = True # No envelope = always compliant | |
| return compliance | |
| def _calculate_convergence_pressure(self, child_traits: Dict[str, float]) -> float: | |
| """ | |
| Calculate convergence pressure for child traits. | |
| Higher pressure indicates more unstable convergence. | |
| """ | |
| if not child_traits: | |
| return 0.0 | |
| total_vp, _ = self.violation_monitor.compute_violation_pressure(child_traits) | |
| return total_vp | |
| def _publish_convergence_event(self, result: ConvergenceResult): | |
| """Publish convergence event to event bus""" | |
| if self.event_bus: | |
| # This would integrate with the event bus from Phase 0.3 | |
| # For now, we'll just log the event | |
| logger.debug(f"Convergence event: {result.convergence_method.value} for {len(result.child_traits)} traits") | |
| def get_convergence_history(self, limit: int = 100) -> List[ConvergenceResult]: | |
| """Get recent convergence history""" | |
| return self.convergence_history[-limit:] | |
| def export_convergence_summary(self) -> Dict[str, Any]: | |
| """Export convergence engine summary""" | |
| if not self.convergence_history: | |
| return {"error": "No convergence history available"} | |
| recent_results = self.convergence_history[-50:] # Last 50 convergences | |
| # Calculate statistics | |
| method_counts = {} | |
| avg_pressure = 0.0 | |
| compliance_rate = 0.0 | |
| for result in recent_results: | |
| # Count convergence methods | |
| method = result.convergence_method.value | |
| method_counts[method] = method_counts.get(method, 0) + 1 | |
| # Accumulate pressure | |
| avg_pressure += result.convergence_pressure | |
| # Calculate compliance rate | |
| compliant_traits = sum(1 for compliant in result.stability_envelope_compliance.values() if compliant) | |
| total_traits = len(result.stability_envelope_compliance) | |
| if total_traits > 0: | |
| compliance_rate += compliant_traits / total_traits | |
| # Calculate averages | |
| if recent_results: | |
| avg_pressure /= len(recent_results) | |
| compliance_rate /= len(recent_results) | |
| return { | |
| "total_convergences": len(self.convergence_history), | |
| "recent_convergences": len(recent_results), | |
| "method_distribution": method_counts, | |
| "average_convergence_pressure": avg_pressure, | |
| "average_compliance_rate": compliance_rate, | |
| "convergence_parameters": self.convergence_parameters, | |
| "system_status": "operational" | |
| } | |
| # Example usage and testing | |
| if __name__ == "__main__": | |
| # Initialize systems | |
| from violation_pressure_calculation import ViolationMonitor | |
| from event_driven_coordination import DjinnEventBus | |
| event_bus = DjinnEventBus() | |
| violation_monitor = ViolationMonitor(event_bus) | |
| convergence_engine = TraitConvergenceEngine(violation_monitor, event_bus) | |
| print("=== Trait Convergence Engine Test ===") | |
| # Test parent traits | |
| parent1_traits = { | |
| "intimacy": 0.8, | |
| "commitment": 0.6, | |
| "caregiving": 0.7, | |
| "violationpressure": 0.2 | |
| } | |
| parent2_traits = { | |
| "intimacy": 0.4, | |
| "commitment": 0.9, | |
| "caregiving": 0.3, | |
| "reflectionindex": 0.8 | |
| } | |
| print(f"Parent 1 traits: {parent1_traits}") | |
| print(f"Parent 2 traits: {parent2_traits}") | |
| # Test different convergence methods | |
| methods = [ | |
| ConvergenceMethod.WEIGHTED_AVERAGE, | |
| ConvergenceMethod.DOMINANCE_INHERITANCE, | |
| ConvergenceMethod.RANDOM_SELECTION, | |
| ConvergenceMethod.STABILITY_OPTIMIZED | |
| ] | |
| for method in methods: | |
| print(f"\n--- Testing {method.value} ---") | |
| result = convergence_engine.converge_traits( | |
| parent1_traits, parent2_traits, | |
| parent1_uuid="parent1", parent2_uuid="parent2", | |
| method=method | |
| ) | |
| print(f"Child traits: {result.child_traits}") | |
| print(f"Convergence pressure: {result.convergence_pressure:.3f}") | |
| print(f"Compliance: {sum(result.stability_envelope_compliance.values())}/{len(result.stability_envelope_compliance)} traits compliant") | |
| print(f"Mutations applied: {result.mutation_applied}") | |
| # Show convergence summary | |
| summary = convergence_engine.export_convergence_summary() | |
| print(f"\n=== Convergence Summary ===") | |
| print(f"Total convergences: {summary['total_convergences']}") | |
| print(f"Method distribution: {summary['method_distribution']}") | |
| print(f"Average pressure: {summary['average_convergence_pressure']:.3f}") | |
| print(f"Average compliance: {summary['average_compliance_rate']:.3f}") | |
| print("=== Phase 0.5 Implementation Complete ===") | |
| print("Trait Convergence Engine operational and mathematically verified.") | |
Xet Storage Details
- Size:
- 18.9 kB
- Xet hash:
- 4ce35997b583725f9e48d454592cfcab1af5ed323893915c8c64e277627403f1
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.