mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
940 lines
35 KiB
Python
940 lines
35 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Hyper-Heuristic Orchestrator for Research Stack
|
|
|
|
Meta-optimization layer that selects between low-level heuristics across
|
|
multiple components: FAMM delay optimization, PIST move selection, and
|
|
infrastructure shim selection.
|
|
|
|
Core idea: Instead of directly solving problems, the hyper-heuristic selects
|
|
which low-level heuristic to apply based on current state, performance metrics,
|
|
and historical patterns.
|
|
"""
|
|
|
|
import json
|
|
import time
|
|
from enum import Enum
|
|
from dataclasses import dataclass, field
|
|
from typing import Dict, List, Optional, Tuple, Any
|
|
from collections import defaultdict
|
|
import random
|
|
|
|
|
|
class HeuristicType(Enum):
|
|
"""Types of low-level heuristics that can be selected."""
|
|
GREEDY = "greedy"
|
|
BALANCED = "balanced"
|
|
CONSERVATIVE = "conservative"
|
|
ADAPTIVE = "adaptive"
|
|
RANDOM = "random"
|
|
|
|
|
|
class ComponentType(Enum):
|
|
"""Components that can use hyper-heuristic optimization."""
|
|
FAMM_DELAY = "famm_delay"
|
|
PIST_MOVE = "pist_move"
|
|
SHIM_SELECTION = "shim_selection"
|
|
GPU_SCHEDULING = "gpu_scheduling"
|
|
FPGA_BUILD = "fpga_build"
|
|
|
|
|
|
@dataclass
|
|
class HeuristicMetrics:
|
|
"""Performance metrics for heuristic evaluation."""
|
|
success_rate: float = 0.0
|
|
avg_cost: float = 0.0
|
|
avg_time: float = 0.0
|
|
total_runs: int = 0
|
|
last_reward: float = 0.0
|
|
|
|
def update(self, success: bool, cost: float, exec_time: float, reward: float):
|
|
"""Update metrics with new execution result."""
|
|
self.total_runs += 1
|
|
|
|
# Exponential moving average for metrics
|
|
alpha = 0.1
|
|
self.success_rate = alpha * (1.0 if success else 0.0) + (1 - alpha) * self.success_rate
|
|
self.avg_cost = alpha * cost + (1 - alpha) * self.avg_cost
|
|
self.avg_time = alpha * exec_time + (1 - alpha) * self.avg_time
|
|
self.last_reward = reward
|
|
|
|
def score(self) -> float:
|
|
"""Compute composite score (higher is better)."""
|
|
# Balance success rate, cost, and time
|
|
return self.success_rate * 100 - self.avg_cost - self.avg_time * 10 + self.last_reward
|
|
|
|
|
|
@dataclass
|
|
class HyperHeuristicState:
|
|
"""State of the hyper-heuristic for a specific component."""
|
|
component: ComponentType
|
|
current_heuristic: HeuristicType
|
|
metrics: Dict[HeuristicType, HeuristicMetrics] = field(default_factory=dict)
|
|
switch_count: int = 0
|
|
total_operations: int = 0
|
|
exploration_rate: float = 0.1 # Epsilon-greedy exploration
|
|
|
|
def __post_init__(self):
|
|
"""Initialize metrics for all heuristic types."""
|
|
for ht in HeuristicType:
|
|
if ht not in self.metrics:
|
|
self.metrics[ht] = HeuristicMetrics()
|
|
|
|
def select_heuristic(self) -> HeuristicType:
|
|
"""Select heuristic using epsilon-greedy strategy."""
|
|
if random.random() < self.exploration_rate:
|
|
# Explore: random selection
|
|
return random.choice(list(HeuristicType))
|
|
else:
|
|
# Exploit: select best performing heuristic
|
|
best_heuristic = self.current_heuristic
|
|
best_score = self.metrics[best_heuristic].score()
|
|
|
|
for ht, metrics in self.metrics.items():
|
|
if metrics.score() > best_score and metrics.total_runs > 0:
|
|
best_score = metrics.score()
|
|
best_heuristic = ht
|
|
|
|
return best_heuristic
|
|
|
|
def should_switch(self, candidate: HeuristicType) -> bool:
|
|
"""Determine if we should switch to candidate heuristic."""
|
|
if candidate == self.current_heuristic:
|
|
return False
|
|
|
|
current_score = self.metrics[self.current_heuristic].score()
|
|
candidate_score = self.metrics[candidate].score()
|
|
|
|
# Switch if candidate is significantly better (10% threshold)
|
|
if candidate_score > current_score * 1.1 and self.metrics[candidate].total_runs > 5:
|
|
return True
|
|
|
|
return False
|
|
|
|
def update(self, heuristic: HeuristicType, success: bool, cost: float,
|
|
exec_time: float, reward: float):
|
|
"""Update state after heuristic execution."""
|
|
self.metrics[heuristic].update(success, cost, exec_time, reward)
|
|
self.total_operations += 1
|
|
|
|
# Decay exploration rate over time
|
|
self.exploration_rate = max(0.01, self.exploration_rate * 0.9995)
|
|
|
|
|
|
class HyperHeuristicOrchestrator:
|
|
"""Main orchestrator managing hyper-heuristics across components."""
|
|
|
|
def __init__(self):
|
|
self.states: Dict[ComponentType, HyperHeuristicState] = {}
|
|
self.global_metrics: Dict[str, Any] = defaultdict(list)
|
|
|
|
def get_state(self, component: ComponentType) -> HyperHeuristicState:
|
|
"""Get or create hyper-heuristic state for component."""
|
|
if component not in self.states:
|
|
default_heuristic = HeuristicType.ADAPTIVE
|
|
self.states[component] = HyperHeuristicState(
|
|
component=component,
|
|
current_heuristic=default_heuristic
|
|
)
|
|
return self.states[component]
|
|
|
|
def select_and_execute(self, component: ComponentType,
|
|
heuristic_func: callable,
|
|
context: Dict[str, Any]) -> Tuple[Any, HeuristicType]:
|
|
"""
|
|
Select heuristic and execute function.
|
|
|
|
Args:
|
|
component: Component type
|
|
heuristic_func: Function that takes (heuristic_type, context) and returns result
|
|
context: Execution context
|
|
|
|
Returns:
|
|
(result, heuristic_used)
|
|
"""
|
|
state = self.get_state(component)
|
|
heuristic = state.select_heuristic()
|
|
|
|
# Check if we should switch
|
|
if state.should_switch(heuristic):
|
|
state.current_heuristic = heuristic
|
|
state.switch_count += 1
|
|
|
|
# Execute with timing
|
|
start_time = time.time()
|
|
try:
|
|
result = heuristic_func(heuristic, context)
|
|
if isinstance(result, dict):
|
|
success = bool(result.get('success', True))
|
|
cost = float(result.get('cost', 0.0 if success else 100.0))
|
|
reward = float(result.get('reward', 1.0 if success else -10.0))
|
|
else:
|
|
success = True
|
|
cost = 0.0
|
|
reward = 1.0
|
|
except Exception as e:
|
|
result = None
|
|
success = False
|
|
cost = 100.0 # Penalty for failure
|
|
reward = -10.0
|
|
print(f"Heuristic execution failed: {e}")
|
|
|
|
exec_time = time.time() - start_time
|
|
|
|
# Update state
|
|
state.update(heuristic, success, cost, exec_time, reward)
|
|
|
|
# Track global metrics
|
|
self.global_metrics[f"{component.value}_{heuristic.value}"].append({
|
|
'success': success,
|
|
'cost': cost,
|
|
'time': exec_time,
|
|
'reward': reward
|
|
})
|
|
|
|
return result, heuristic
|
|
|
|
def get_performance_report(self) -> Dict[str, Any]:
|
|
"""Generate performance report for all components."""
|
|
report = {
|
|
'components': {},
|
|
'global_stats': {}
|
|
}
|
|
|
|
for component, state in self.states.items():
|
|
component_report = {
|
|
'current_heuristic': state.current_heuristic.value,
|
|
'switch_count': state.switch_count,
|
|
'total_operations': state.total_operations,
|
|
'exploration_rate': state.exploration_rate,
|
|
'heuristic_metrics': {}
|
|
}
|
|
|
|
for ht, metrics in state.metrics.items():
|
|
component_report['heuristic_metrics'][ht.value] = {
|
|
'success_rate': metrics.success_rate,
|
|
'avg_cost': metrics.avg_cost,
|
|
'avg_time': metrics.avg_time,
|
|
'total_runs': metrics.total_runs,
|
|
'score': metrics.score()
|
|
}
|
|
|
|
report['components'][component.value] = component_report
|
|
|
|
# Global statistics
|
|
total_ops = sum(s.total_operations for s in self.states.values())
|
|
total_switches = sum(s.switch_count for s in self.states.values())
|
|
report['global_stats'] = {
|
|
'total_operations': total_ops,
|
|
'total_switches': total_switches,
|
|
'switch_rate': total_switches / max(1, total_ops)
|
|
}
|
|
|
|
return report
|
|
|
|
def save_state(self, filepath: str):
|
|
"""Save hyper-heuristic state to file."""
|
|
state_data = {
|
|
'states': {},
|
|
'global_metrics': dict(self.global_metrics)
|
|
}
|
|
|
|
for component, state in self.states.items():
|
|
state_data['states'][component.value] = {
|
|
'current_heuristic': state.current_heuristic.value,
|
|
'metrics': {
|
|
ht.value: {
|
|
'success_rate': m.success_rate,
|
|
'avg_cost': m.avg_cost,
|
|
'avg_time': m.avg_time,
|
|
'total_runs': m.total_runs,
|
|
'last_reward': m.last_reward
|
|
}
|
|
for ht, m in state.metrics.items()
|
|
},
|
|
'switch_count': state.switch_count,
|
|
'total_operations': state.total_operations,
|
|
'exploration_rate': state.exploration_rate
|
|
}
|
|
|
|
with open(filepath, 'w') as f:
|
|
json.dump(state_data, f, indent=2)
|
|
|
|
def load_state(self, filepath: str):
|
|
"""Load hyper-heuristic state from file."""
|
|
with open(filepath, 'r') as f:
|
|
state_data = json.load(f)
|
|
|
|
for component_str, component_state in state_data['states'].items():
|
|
component = ComponentType(component_str)
|
|
current_heuristic = HeuristicType(component_state['current_heuristic'])
|
|
|
|
metrics = {}
|
|
for ht_str, m_data in component_state['metrics'].items():
|
|
ht = HeuristicType(ht_str)
|
|
metrics[ht] = HeuristicMetrics(
|
|
success_rate=m_data['success_rate'],
|
|
avg_cost=m_data['avg_cost'],
|
|
avg_time=m_data['avg_time'],
|
|
total_runs=m_data['total_runs'],
|
|
last_reward=m_data['last_reward']
|
|
)
|
|
|
|
self.states[component] = HyperHeuristicState(
|
|
component=component,
|
|
current_heuristic=current_heuristic,
|
|
metrics=metrics,
|
|
switch_count=component_state['switch_count'],
|
|
total_operations=component_state['total_operations'],
|
|
exploration_rate=component_state['exploration_rate']
|
|
)
|
|
|
|
self.global_metrics = defaultdict(list, state_data['global_metrics'])
|
|
|
|
|
|
# FAMM-specific hyper-heuristics
|
|
class FAMMHyperHeuristics:
|
|
"""FAMM delay optimization hyper-heuristics."""
|
|
|
|
@staticmethod
|
|
def greedy_minimize(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Greedy delay minimization - always minimize delay."""
|
|
bank = context.get('bank', {})
|
|
address = context.get('address', 0)
|
|
target_delay = context.get('target_delay', 1.0)
|
|
max_delay = context.get('max_delay', 10.0)
|
|
|
|
adjusted_delay = min(target_delay, max_delay)
|
|
|
|
return {
|
|
'strategy': 'greedy_minimize',
|
|
'adjusted_delay': adjusted_delay,
|
|
'success': adjusted_delay <= max_delay
|
|
}
|
|
|
|
@staticmethod
|
|
def frustration_balance(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Balance competing delays to minimize frustration."""
|
|
bank = context.get('bank', {})
|
|
address = context.get('address', 0)
|
|
target_delay = context.get('target_delay', 1.0)
|
|
max_delay = context.get('max_delay', 10.0)
|
|
|
|
# Simulate frustration balancing by averaging with existing delay
|
|
current_delay = bank.get('cells', {}).get(address, {}).get('delay', target_delay)
|
|
adjusted_delay = min((current_delay + target_delay) / 2, max_delay)
|
|
|
|
return {
|
|
'strategy': 'frustration_balance',
|
|
'adjusted_delay': adjusted_delay,
|
|
'success': adjusted_delay <= max_delay
|
|
}
|
|
|
|
@staticmethod
|
|
def adaptive_weight(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Adaptive weighting based on delay mass and weight."""
|
|
bank = context.get('bank', {})
|
|
address = context.get('address', 0)
|
|
target_delay = context.get('target_delay', 1.0)
|
|
max_delay = context.get('max_delay', 10.0)
|
|
|
|
cell = bank.get('cells', {}).get(address, {})
|
|
delay_weight = cell.get('delay_weight', 1.0)
|
|
weight = delay_weight / (delay_weight + 1.0)
|
|
current_delay = cell.get('delay', target_delay)
|
|
|
|
adjusted_delay = min(current_delay * weight + target_delay * (1 - weight), max_delay)
|
|
|
|
return {
|
|
'strategy': 'adaptive_weight',
|
|
'adjusted_delay': adjusted_delay,
|
|
'success': adjusted_delay <= max_delay
|
|
}
|
|
|
|
|
|
# PIST-specific hyper-heuristics
|
|
class PISTHyperHeuristics:
|
|
"""PIST move selection hyper-heuristics."""
|
|
|
|
@staticmethod
|
|
def linear_move(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Select linear move (step within shell)."""
|
|
pos = context.get('pos', {'k': 0, 't': 0})
|
|
k = pos.get('k', 0)
|
|
t = pos.get('t', 0)
|
|
|
|
# Linear step: increment or decrement t
|
|
new_t = t + 1 if t < 2 * k else t - 1
|
|
|
|
return {
|
|
'strategy': 'linear',
|
|
'move_type': 'linearStep',
|
|
'new_pos': {'k': k, 't': new_t},
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def resonance_jump(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Select resonance jump (preserve mass)."""
|
|
pos = context.get('pos', {'k': 0, 't': 0})
|
|
k = pos.get('k', 0)
|
|
t = pos.get('t', 0)
|
|
|
|
# Mirror position to preserve mass
|
|
new_t = 2 * k + 1 - t
|
|
|
|
return {
|
|
'strategy': 'resonance',
|
|
'move_type': 'resonanceJump',
|
|
'new_pos': {'k': k, 't': new_t},
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def adaptive_move(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Adaptive move selection based on phase."""
|
|
pos = context.get('pos', {'k': 0, 't': 0})
|
|
phase = context.get('phase', 'grounded')
|
|
|
|
if phase == 'seismic':
|
|
# Use resonance jumps for seismic phase
|
|
return PISTHyperHeuristics.resonance_jump(heuristic, context)
|
|
else:
|
|
# Use linear moves for grounded phase
|
|
return PISTHyperHeuristics.linear_move(heuristic, context)
|
|
|
|
|
|
# Infrastructure shim selection hyper-heuristics
|
|
class ShimSelectionHyperHeuristics:
|
|
"""Infrastructure shim selection hyper-heuristics."""
|
|
|
|
@staticmethod
|
|
def select_by_domain(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Select shim based on problem domain."""
|
|
domain = context.get('domain', 'general')
|
|
task_type = context.get('task_type', 'unknown')
|
|
|
|
# Domain-based shim mapping
|
|
shim_map = {
|
|
'math': ['math_prover_prior_metaprobe.py', 'intense_math_modeling_router.py'],
|
|
'compression': ['compression_signal_shaping_synthesis.py', 'semantic_compression_theoretical_limits_prior.py'],
|
|
'hardware': ['tang9k_uart_beacon_probe.py', 'fpga_nanokernel_rrc_analysis.py'],
|
|
'general': ['stack_solidification_audit.py', 'parallel_metaprobe_launcher.py']
|
|
}
|
|
|
|
candidates = shim_map.get(domain, shim_map['general'])
|
|
selected = candidates[0] if candidates else 'default_shim.py'
|
|
|
|
return {
|
|
'strategy': 'domain_based',
|
|
'selected_shim': selected,
|
|
'candidates': candidates,
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def select_by_performance(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Select shim based on historical performance."""
|
|
domain = context.get('domain', 'general')
|
|
performance_history = context.get('performance_history', {})
|
|
|
|
# Select best performing shim for domain
|
|
if domain in performance_history:
|
|
best_shim = max(performance_history[domain].items(), key=lambda x: x[1])[0]
|
|
else:
|
|
best_shim = 'default_shim.py'
|
|
|
|
return {
|
|
'strategy': 'performance_based',
|
|
'selected_shim': best_shim,
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def select_adaptive(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Adaptive shim selection combining domain and performance."""
|
|
domain = context.get('domain', 'general')
|
|
performance_history = context.get('performance_history', {})
|
|
|
|
# Try performance-based first, fall back to domain-based
|
|
if domain in performance_history and performance_history[domain]:
|
|
return ShimSelectionHyperHeuristics.select_by_performance(heuristic, context)
|
|
else:
|
|
return ShimSelectionHyperHeuristics.select_by_domain(heuristic, context)
|
|
|
|
|
|
# GPU scheduling hyper-heuristics
|
|
class GPUSchedulingHyperHeuristics:
|
|
"""GPU task scheduling hyper-heuristics for RTX 4070."""
|
|
|
|
@staticmethod
|
|
def round_robin(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Round-robin task scheduling across GPU resources."""
|
|
task_queue = context.get('task_queue', [])
|
|
gpu_count = context.get('gpu_count', 1)
|
|
current_gpu = context.get('current_gpu', 0)
|
|
|
|
if not task_queue:
|
|
return {'strategy': 'round_robin', 'assigned': [], 'success': True}
|
|
|
|
# Assign tasks in round-robin fashion
|
|
assigned = []
|
|
for i, task in enumerate(task_queue):
|
|
gpu_id = (current_gpu + i) % gpu_count
|
|
assigned.append({'task': task, 'gpu_id': gpu_id})
|
|
|
|
return {
|
|
'strategy': 'round_robin',
|
|
'assigned': assigned,
|
|
'next_gpu': (current_gpu + len(task_queue)) % gpu_count,
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def priority_based(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Priority-based scheduling considering task urgency and resource requirements."""
|
|
task_queue = context.get('task_queue', [])
|
|
gpu_memory = context.get('gpu_memory', 12000) # RTX 4070: ~12GB
|
|
gpu_count = context.get('gpu_count', 1)
|
|
|
|
# Sort by priority (higher priority first)
|
|
sorted_tasks = sorted(task_queue, key=lambda t: t.get('priority', 0), reverse=True)
|
|
|
|
assigned = []
|
|
memory_used = 0
|
|
|
|
for task in sorted_tasks:
|
|
task_memory = task.get('memory_required', 1000)
|
|
|
|
# Find GPU with sufficient memory
|
|
if memory_used + task_memory <= gpu_memory:
|
|
assigned.append({'task': task, 'gpu_id': 0, 'reason': 'memory_available'})
|
|
memory_used += task_memory
|
|
else:
|
|
assigned.append({'task': task, 'gpu_id': None, 'reason': 'insufficient_memory'})
|
|
|
|
return {
|
|
'strategy': 'priority_based',
|
|
'assigned': assigned,
|
|
'memory_utilization': memory_used / gpu_memory,
|
|
'success': memory_used <= gpu_memory
|
|
}
|
|
|
|
@staticmethod
|
|
def load_balancing(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Load-aware balancing across GPU resources."""
|
|
task_queue = context.get('task_queue', [])
|
|
gpu_states = context.get('gpu_states', [{'load': 0.5, 'memory': 6000}])
|
|
|
|
assigned = []
|
|
|
|
for task in enumerate(task_queue):
|
|
# Select least loaded GPU
|
|
best_gpu = min(range(len(gpu_states)), key=lambda i: gpu_states[i]['load'])
|
|
|
|
task_load = task[1].get('estimated_load', 0.1)
|
|
gpu_states[best_gpu]['load'] += task_load
|
|
|
|
assigned.append({
|
|
'task': task[1],
|
|
'gpu_id': best_gpu,
|
|
'gpu_load_before': gpu_states[best_gpu]['load'] - task_load,
|
|
'gpu_load_after': gpu_states[best_gpu]['load']
|
|
})
|
|
|
|
return {
|
|
'strategy': 'load_balancing',
|
|
'assigned': assigned,
|
|
'final_gpu_states': gpu_states,
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def memory_aware(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Memory-aware scheduling for large model workloads."""
|
|
task_queue = context.get('task_queue', [])
|
|
gpu_memory_total = context.get('gpu_memory', 12000)
|
|
current_usage = context.get('current_memory_usage', 0)
|
|
|
|
# Group tasks by memory requirements
|
|
large_tasks = [t for t in task_queue if t.get('memory_required', 0) > 4000]
|
|
small_tasks = [t for t in task_queue if t.get('memory_required', 0) <= 4000]
|
|
|
|
assigned = []
|
|
memory_used = current_usage
|
|
|
|
# Schedule large tasks first (they're harder to place)
|
|
for task in large_tasks:
|
|
task_memory = task.get('memory_required', 5000)
|
|
if memory_used + task_memory <= gpu_memory_total:
|
|
assigned.append({'task': task, 'gpu_id': 0, 'reason': 'large_task_fit'})
|
|
memory_used += task_memory
|
|
else:
|
|
assigned.append({'task': task, 'gpu_id': None, 'reason': 'insufficient_memory'})
|
|
|
|
# Fill remaining space with small tasks
|
|
for task in small_tasks:
|
|
task_memory = task.get('memory_required', 1000)
|
|
if memory_used + task_memory <= gpu_memory_total:
|
|
assigned.append({'task': task, 'gpu_id': 0, 'reason': 'small_task_fill'})
|
|
memory_used += task_memory
|
|
else:
|
|
assigned.append({'task': task, 'gpu_id': None, 'reason': 'insufficient_memory'})
|
|
|
|
return {
|
|
'strategy': 'memory_aware',
|
|
'assigned': assigned,
|
|
'memory_utilization': memory_used / gpu_memory_total,
|
|
'large_tasks_scheduled': len([a for a in assigned if a['gpu_id'] is not None and a['task'].get('memory_required', 0) > 4000]),
|
|
'success': memory_used <= gpu_memory_total
|
|
}
|
|
|
|
|
|
# FPGA build optimization hyper-heuristics
|
|
class FPGABuildHyperHeuristics:
|
|
"""FPGA build and simulation optimization hyper-heuristics."""
|
|
|
|
@staticmethod
|
|
def incremental_build(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Incremental build strategy - only rebuild changed modules."""
|
|
changed_files = context.get('changed_files', [])
|
|
build_cache = context.get('build_cache', {})
|
|
|
|
modules_to_rebuild = []
|
|
cache_hits = []
|
|
|
|
for file in changed_files:
|
|
if file in build_cache:
|
|
cache_hits.append(file)
|
|
else:
|
|
modules_to_rebuild.append(file)
|
|
|
|
return {
|
|
'strategy': 'incremental_build',
|
|
'modules_to_rebuild': modules_to_rebuild,
|
|
'cache_hits': cache_hits,
|
|
'estimated_speedup': len(cache_hits) / max(1, len(changed_files)),
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def parallel_synthesis(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Parallel synthesis strategy for independent modules."""
|
|
modules = context.get('modules', [])
|
|
dependency_graph = context.get('dependency_graph', {})
|
|
available_cores = context.get('available_cores', 4)
|
|
|
|
# Identify independent modules (no dependencies)
|
|
independent_modules = []
|
|
dependent_modules = []
|
|
|
|
for module in modules:
|
|
deps = dependency_graph.get(module, [])
|
|
if not deps or all(dep not in modules for dep in deps):
|
|
independent_modules.append(module)
|
|
else:
|
|
dependent_modules.append(module)
|
|
|
|
# Schedule independent modules in parallel
|
|
parallel_slots = min(len(independent_modules), available_cores)
|
|
|
|
return {
|
|
'strategy': 'parallel_synthesis',
|
|
'parallel_slots': parallel_slots,
|
|
'independent_modules': independent_modules,
|
|
'dependent_modules': dependent_modules,
|
|
'estimated_speedup': parallel_slots / max(1, len(modules)),
|
|
'success': True
|
|
}
|
|
|
|
@staticmethod
|
|
def resource_aware(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Resource-aware synthesis considering FPGA resource constraints."""
|
|
modules = context.get('modules', [])
|
|
resource_budget = context.get('resource_budget', {'LUT': 43200, 'FF': 86400, 'BRAM': 120})
|
|
module_resources = context.get('module_resources', {})
|
|
|
|
scheduled = []
|
|
resource_used = {'LUT': 0, 'FF': 0, 'BRAM': 0}
|
|
deferred = []
|
|
|
|
for module in modules:
|
|
req = module_resources.get(module, {'LUT': 1000, 'FF': 2000, 'BRAM': 1})
|
|
|
|
# Check if module fits
|
|
fits = all(
|
|
resource_used[r] + req[r] <= resource_budget[r]
|
|
for r in ['LUT', 'FF', 'BRAM']
|
|
)
|
|
|
|
if fits:
|
|
scheduled.append(module)
|
|
for r in ['LUT', 'FF', 'BRAM']:
|
|
resource_used[r] += req[r]
|
|
else:
|
|
deferred.append(module)
|
|
|
|
return {
|
|
'strategy': 'resource_aware',
|
|
'scheduled': scheduled,
|
|
'deferred': deferred,
|
|
'resource_utilization': {
|
|
r: resource_used[r] / resource_budget[r] for r in ['LUT', 'FF', 'BRAM']
|
|
},
|
|
'success': len(deferred) == 0
|
|
}
|
|
|
|
@staticmethod
|
|
def timing_driven(heuristic: HeuristicType, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Timing-driven synthesis for critical path optimization."""
|
|
modules = context.get('modules', [])
|
|
timing_constraints = context.get('timing_constraints', {})
|
|
critical_paths = context.get('critical_paths', [])
|
|
|
|
# Prioritize modules on critical paths
|
|
priority_map = {}
|
|
for i, path in enumerate(critical_paths):
|
|
for module in path:
|
|
priority_map[module] = priority_map.get(module, 0) + (len(critical_paths) - i)
|
|
|
|
# Sort modules by priority (critical path modules first)
|
|
sorted_modules = sorted(
|
|
modules,
|
|
key=lambda m: priority_map.get(m, 0),
|
|
reverse=True
|
|
)
|
|
|
|
return {
|
|
'strategy': 'timing_driven',
|
|
'module_priority': priority_map,
|
|
'build_order': sorted_modules,
|
|
'critical_modules': [m for m in sorted_modules if priority_map.get(m, 0) > 0],
|
|
'success': True
|
|
}
|
|
|
|
|
|
def demo_famm_hyperheuristic():
|
|
"""Demonstrate FAMM hyper-heuristic optimization."""
|
|
print("=== FAMM Hyper-Heuristic Demo ===")
|
|
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
|
|
# Simulate FAMM operations
|
|
for i in range(20):
|
|
context = {
|
|
'bank': {
|
|
'cells': {
|
|
0: {'delay': 5.0, 'delay_weight': 1.0},
|
|
1: {'delay': 3.0, 'delay_weight': 0.5}
|
|
}
|
|
},
|
|
'address': i % 2,
|
|
'target_delay': 4.0,
|
|
'max_delay': 10.0
|
|
}
|
|
|
|
# Route to appropriate heuristic function based on current selection
|
|
def famm_heuristic_func(ht, ctx):
|
|
if ht == HeuristicType.GREEDY:
|
|
return FAMMHyperHeuristics.greedy_minimize(ht, ctx)
|
|
elif ht == HeuristicType.BALANCED:
|
|
return FAMMHyperHeuristics.frustration_balance(ht, ctx)
|
|
elif ht == HeuristicType.ADAPTIVE:
|
|
return FAMMHyperHeuristics.adaptive_weight(ht, ctx)
|
|
else:
|
|
return FAMMHyperHeuristics.greedy_minimize(ht, ctx)
|
|
|
|
result, heuristic = orchestrator.select_and_execute(
|
|
ComponentType.FAMM_DELAY, famm_heuristic_func, context
|
|
)
|
|
|
|
print(f"Op {i+1}: {heuristic.value} -> delay={result['adjusted_delay']:.2f}, success={result['success']}")
|
|
|
|
report = orchestrator.get_performance_report()
|
|
print("\n=== FAMM Performance Report ===")
|
|
print(json.dumps(report['components']['famm_delay'], indent=2))
|
|
|
|
|
|
def demo_pist_hyperheuristic():
|
|
"""Demonstrate PIST hyper-heuristic optimization."""
|
|
print("\n=== PIST Hyper-Heuristic Demo ===")
|
|
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
|
|
# Simulate PIST operations
|
|
for i in range(15):
|
|
context = {
|
|
'pos': {'k': i % 5, 't': i % 10},
|
|
'phase': 'seismic' if i % 3 == 0 else 'grounded'
|
|
}
|
|
|
|
def pist_heuristic_func(ht, ctx):
|
|
if ht == HeuristicType.GREEDY:
|
|
return PISTHyperHeuristics.linear_move(ht, ctx)
|
|
elif ht == HeuristicType.ADAPTIVE:
|
|
return PISTHyperHeuristics.adaptive_move(ht, ctx)
|
|
else:
|
|
return PISTHyperHeuristics.resonance_jump(ht, ctx)
|
|
|
|
result, heuristic = orchestrator.select_and_execute(
|
|
ComponentType.PIST_MOVE, pist_heuristic_func, context
|
|
)
|
|
|
|
print(f"Op {i+1}: {heuristic.value} -> {result['move_type']}, pos={result['new_pos']}")
|
|
|
|
report = orchestrator.get_performance_report()
|
|
print("\n=== PIST Performance Report ===")
|
|
print(json.dumps(report['components']['pist_move'], indent=2))
|
|
|
|
|
|
def demo_shim_selection_hyperheuristic():
|
|
"""Demonstrate infrastructure shim selection hyper-heuristic."""
|
|
print("\n=== Shim Selection Hyper-Heuristic Demo ===")
|
|
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
|
|
# Simulate shim selection
|
|
domains = ['math', 'compression', 'hardware', 'general']
|
|
performance_history = {
|
|
'math': {'math_prover_prior_metaprobe.py': 0.9, 'intense_math_modeling_router.py': 0.7},
|
|
'compression': {'compression_signal_shaping_synthesis.py': 0.8}
|
|
}
|
|
|
|
for i in range(12):
|
|
context = {
|
|
'domain': domains[i % len(domains)],
|
|
'task_type': 'optimization',
|
|
'performance_history': performance_history
|
|
}
|
|
|
|
def shim_heuristic_func(ht, ctx):
|
|
if ht == HeuristicType.GREEDY:
|
|
return ShimSelectionHyperHeuristics.select_by_domain(ht, ctx)
|
|
elif ht == HeuristicType.ADAPTIVE:
|
|
return ShimSelectionHyperHeuristics.select_adaptive(ht, ctx)
|
|
else:
|
|
return ShimSelectionHyperHeuristics.select_by_performance(ht, ctx)
|
|
|
|
result, heuristic = orchestrator.select_and_execute(
|
|
ComponentType.SHIM_SELECTION, shim_heuristic_func, context
|
|
)
|
|
|
|
print(f"Op {i+1}: {heuristic.value} -> {result['selected_shim']}")
|
|
|
|
report = orchestrator.get_performance_report()
|
|
print("\n=== Shim Selection Performance Report ===")
|
|
print(json.dumps(report['components']['shim_selection'], indent=2))
|
|
|
|
|
|
def demo_gpu_scheduling_hyperheuristic():
|
|
"""Demonstrate GPU scheduling hyper-heuristic."""
|
|
print("\n=== GPU Scheduling Hyper-Heuristic Demo ===")
|
|
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
|
|
# Simulate GPU task scheduling
|
|
for i in range(15):
|
|
task_queue = [
|
|
{'name': f'task_{i}_{j}', 'priority': (i+j) % 10, 'memory_required': 1000 + (i*j % 4000)}
|
|
for j in range(3)
|
|
]
|
|
|
|
context = {
|
|
'task_queue': task_queue,
|
|
'gpu_memory': 12000,
|
|
'gpu_count': 1,
|
|
'current_memory_usage': i * 500,
|
|
'gpu_states': [{'load': 0.3 + (i % 5) * 0.1, 'memory': 6000}]
|
|
}
|
|
|
|
def gpu_heuristic_func(ht, ctx):
|
|
if ht == HeuristicType.GREEDY:
|
|
return GPUSchedulingHyperHeuristics.round_robin(ht, ctx)
|
|
elif ht == HeuristicType.BALANCED:
|
|
return GPUSchedulingHyperHeuristics.priority_based(ht, ctx)
|
|
elif ht == HeuristicType.ADAPTIVE:
|
|
return GPUSchedulingHyperHeuristics.memory_aware(ht, ctx)
|
|
else:
|
|
return GPUSchedulingHyperHeuristics.load_balancing(ht, ctx)
|
|
|
|
result, heuristic = orchestrator.select_and_execute(
|
|
ComponentType.GPU_SCHEDULING, gpu_heuristic_func, context
|
|
)
|
|
|
|
memory_util = result.get('memory_utilization', 0)
|
|
scheduled = len([a for a in result.get('assigned', []) if a.get('gpu_id') is not None])
|
|
print(f"Op {i+1}: {heuristic.value} -> {scheduled}/{len(task_queue)} tasks, mem={memory_util:.2%}")
|
|
|
|
report = orchestrator.get_performance_report()
|
|
print("\n=== GPU Scheduling Performance Report ===")
|
|
print(json.dumps(report['components']['gpu_scheduling'], indent=2))
|
|
|
|
|
|
def demo_fpga_build_hyperheuristic():
|
|
"""Demonstrate FPGA build optimization hyper-heuristic."""
|
|
print("\n=== FPGA Build Hyper-Heuristic Demo ===")
|
|
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
|
|
# Simulate FPGA build optimization
|
|
for i in range(12):
|
|
modules = [f'module_{j}' for j in range(5)]
|
|
changed_files = [f'{m}.v' for m in modules if (i + hash(m)) % 3 == 0]
|
|
|
|
context = {
|
|
'modules': modules,
|
|
'changed_files': changed_files,
|
|
'build_cache': {f: f'cached_{f}' for f in changed_files if hash(f) % 2 == 0},
|
|
'dependency_graph': {
|
|
f'module_{j}': [f'module_{k}' for k in range(j)] if j > 0 else []
|
|
for j in range(5)
|
|
},
|
|
'available_cores': 4,
|
|
'resource_budget': {'LUT': 43200, 'FF': 86400, 'BRAM': 120},
|
|
'module_resources': {
|
|
f'module_{j}': {'LUT': 1000 * (j+1), 'FF': 2000 * (j+1), 'BRAM': j+1}
|
|
for j in range(5)
|
|
},
|
|
'critical_paths': [['module_0', 'module_2', 'module_4'], ['module_1', 'module_3']]
|
|
}
|
|
|
|
def fpga_heuristic_func(ht, ctx):
|
|
if ht == HeuristicType.GREEDY:
|
|
return FPGABuildHyperHeuristics.incremental_build(ht, ctx)
|
|
elif ht == HeuristicType.BALANCED:
|
|
return FPGABuildHyperHeuristics.parallel_synthesis(ht, ctx)
|
|
elif ht == HeuristicType.ADAPTIVE:
|
|
return FPGABuildHyperHeuristics.resource_aware(ht, ctx)
|
|
else:
|
|
return FPGABuildHyperHeuristics.timing_driven(ht, ctx)
|
|
|
|
result, heuristic = orchestrator.select_and_execute(
|
|
ComponentType.FPGA_BUILD, fpga_heuristic_func, context
|
|
)
|
|
|
|
speedup = result.get('estimated_speedup', 0)
|
|
success = result.get('success', False)
|
|
print(f"Op {i+1}: {heuristic.value} -> speedup={speedup:.2f}x, success={success}")
|
|
|
|
report = orchestrator.get_performance_report()
|
|
print("\n=== FPGA Build Performance Report ===")
|
|
print(json.dumps(report['components']['fpga_build'], indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
demo_famm_hyperheuristic()
|
|
demo_pist_hyperheuristic()
|
|
demo_shim_selection_hyperheuristic()
|
|
demo_gpu_scheduling_hyperheuristic()
|
|
demo_fpga_build_hyperheuristic()
|
|
|
|
print("\n=== Global Statistics ===")
|
|
orchestrator = HyperHeuristicOrchestrator()
|
|
# Run demos to populate orchestrator
|
|
demo_famm_hyperheuristic()
|
|
demo_pist_hyperheuristic()
|
|
demo_shim_selection_hyperheuristic()
|
|
demo_gpu_scheduling_hyperheuristic()
|
|
demo_fpga_build_hyperheuristic()
|
|
|
|
# Note: In real usage, you'd use a single orchestrator instance across demos
|