tostido's picture
download
raw
18.9 kB
# 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"
@dataclass
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.