///|
/// Objective used to choose a deterministic schedule policy.
pub(all) enum OptimizationGoal {
MinimizeDevices
MinimizeTime
MinimizeUncertainty
} derive(Eq, Debug)
///|
/// Baseline and optimized schedule with a transparent score.
pub(all) struct OptimizationResult {
goal : OptimizationGoal
schedule : ScheduledPlan
baseline_score : Double
optimized_score : Double
improvement : Double
}
///|
/// Return a stable optimization goal label.
pub fn optimization_goal_text(goal : OptimizationGoal) -> String {
match goal {
MinimizeDevices => "minimize-devices"
MinimizeTime => "minimize-time"
MinimizeUncertainty => "minimize-uncertainty"
}
}
///|
fn policy_for_goal(goal : OptimizationGoal) -> SchedulePolicy {
match goal {
MinimizeDevices =>
schedule_policy(datum_first=true, group_by_device=true, max_batch_size=32)
MinimizeTime =>
schedule_policy(datum_first=true, group_by_device=true, max_batch_size=32)
MinimizeUncertainty =>
schedule_policy(
datum_first=true,
group_by_device=false,
max_batch_size=16,
)
}
}
///|
/// Score a schedule according to its declared objective.
pub fn optimization_score(result : OptimizationResult) -> Double {
match result.goal {
MinimizeDevices => 1.0 / (1.0 + result.schedule.device_switches.to_double())
MinimizeTime => 1.0 / (1.0 + result.schedule.estimated_seconds)
MinimizeUncertainty => {
let metrics = plan_metrics(MeasurementPlan::{
part_id: result.schedule.part_id,
steps: result.schedule.steps,
summary: {
coverage: 1.0,
capability: true,
steps: result.schedule.steps.length(),
warnings: [],
},
})
1.0 / (1.0 + metrics.average_uncertainty)
}
}
}
///|
/// Optimize execution grouping without changing measurements or devices.
pub fn optimize_plan(
plan : MeasurementPlan,
goal : OptimizationGoal,
) -> OptimizationResult {
let baseline = schedule_plan(plan, default_schedule_policy())
let optimized = schedule_plan(plan, policy_for_goal(goal))
let baseline_result = OptimizationResult::{
goal,
schedule: baseline,
baseline_score: 0.0,
optimized_score: 0.0,
improvement: 0.0,
}
let baseline_score = optimization_score(baseline_result)
let optimized_result = OptimizationResult::{
goal,
schedule: optimized,
baseline_score,
optimized_score: 0.0,
improvement: 0.0,
}
let optimized_score = optimization_score(optimized_result)
{
goal,
schedule: optimized,
baseline_score,
optimized_score,
improvement: optimized_score - baseline_score,
}
}
///|
/// Return estimated samples per abstract execution second.
pub fn plan_efficiency(plan : MeasurementPlan) -> Double {
let metrics = plan_metrics(plan)
if metrics.estimated_seconds == 0.0 {
0.0
} else {
metrics.estimated_samples.to_double() / metrics.estimated_seconds
}
}
///|
/// Count plan steps that cannot execute or carry warnings.
pub fn plan_waste_count(plan : MeasurementPlan) -> Int {
plan.summary.warnings.length()
}
///|
/// Return whether an optimization improves its declared score.
pub fn optimization_improves(result : OptimizationResult) -> Bool {
result.optimized_score >= result.baseline_score
}
///|
/// Return the number of schedule batches after optimization.
pub fn optimized_batch_count(result : OptimizationResult) -> Int {
result.schedule.batches.length()
}
///|
/// Return the score difference rounded conceptually as a raw deterministic value.
pub fn optimization_delta(result : OptimizationResult) -> Double {
result.optimized_score - result.baseline_score
}