use super::*;
#[derive(Clone, Debug)]
pub(crate) struct PathDemotionRecord {
pub(crate) seed_idx: usize,
pub(crate) regime: crate::solver::continuation_path::PathRegime,
pub(crate) reason: String,
}
#[derive(Clone, Debug)]
pub struct InnerProgressFeedback {
pub cap: Arc<AtomicUsize>,
pub accepted_iter: Arc<AtomicUsize>,
pub last_iters: Arc<AtomicUsize>,
pub last_converged: Arc<AtomicBool>,
pub ift_residual: Arc<AtomicU64>,
pub accept_rho: Arc<AtomicU64>,
}
impl InnerProgressFeedback {
pub(crate) fn snapshot(&self) -> Option<InnerProgressSnapshot> {
let iters = self.last_iters.load(Ordering::Relaxed);
if iters == 0 {
None
} else {
let residual_bits = self.ift_residual.load(Ordering::Relaxed);
let r = f64::from_bits(residual_bits);
let last_ift_residual = if r.is_finite() && r >= 0.0 {
Some(r)
} else {
None
};
let accept_rho_bits = self.accept_rho.load(Ordering::Relaxed);
let ar = f64::from_bits(accept_rho_bits);
let last_accept_rho = if ar.is_finite() && ar >= 0.0 {
Some(ar)
} else {
None
};
Some(InnerProgressSnapshot {
last_iters: iters,
last_converged: self.last_converged.load(Ordering::Relaxed),
last_ift_residual,
last_accept_rho,
})
}
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct InnerProgressSnapshot {
pub(crate) last_iters: usize,
pub(crate) last_converged: bool,
pub(crate) last_ift_residual: Option<f64>,
pub(crate) last_accept_rho: Option<f64>,
}
#[inline]
pub(crate) fn effective_seed_budget(
requested_budget: usize,
solver: Solver,
risk_profile: crate::seeding::SeedRiskProfile,
_screening_enabled: bool,
) -> usize {
let requested_budget = requested_budget.max(1);
match (solver, risk_profile) {
(Solver::Efs | Solver::HybridEfs, _) => 1,
(Solver::Arc, crate::seeding::SeedRiskProfile::Survival) => 1,
(Solver::Arc, crate::seeding::SeedRiskProfile::GeneralizedLinear) => 2,
_ => requested_budget,
}
}
#[inline]
pub(crate) fn should_screen_seeds(
config: &OuterConfig,
solver: Solver,
generated_seed_count: usize,
seed_budget: usize,
) -> bool {
if matches!(solver, Solver::Efs | Solver::HybridEfs) {
return false;
}
if config.initial_rho.is_some() && seed_budget == 1 && !config.screen_initial_rho {
return false;
}
config.screening_cap.is_some()
&& generated_seed_count > seed_budget
&& matches!(solver, Solver::Arc | Solver::Bfgs)
}
#[inline]
pub(crate) fn expensive_unsuccessful_seed_limit(
solver: Solver,
risk_profile: crate::seeding::SeedRiskProfile,
) -> Option<usize> {
match (solver, risk_profile) {
(Solver::Efs | Solver::HybridEfs, _) => Some(1),
(Solver::Arc, crate::seeding::SeedRiskProfile::Survival) => Some(1),
(Solver::Arc, crate::seeding::SeedRiskProfile::GeneralizedLinear) => Some(2),
_ => None,
}
}
pub(crate) const SEED_SCREENING_CASCADE_MULTIPLIERS: [usize; 3] = [1, 4, 16];
pub(crate) const SEED_SCREENING_UNCAPPED: usize = 0;
pub(crate) fn rank_seeds_with_screening(
obj: &mut dyn OuterObjective,
config: &OuterConfig,
context: &str,
seeds: &[Array1<f64>],
) -> Vec<Array1<f64>> {
let Some(screening_cap) = config.screening_cap.as_ref() else {
return seeds.to_vec();
};
let initial_cap = config.seed_config.screen_max_inner_iterations.max(1);
let previous_cap = screening_cap.swap(initial_cap, Ordering::Relaxed);
let cascade_caps = [
PriorityBudgetStage {
cap: initial_cap.saturating_mul(SEED_SCREENING_CASCADE_MULTIPLIERS[0]),
},
PriorityBudgetStage {
cap: initial_cap.saturating_mul(SEED_SCREENING_CASCADE_MULTIPLIERS[1]),
},
PriorityBudgetStage {
cap: initial_cap.saturating_mul(SEED_SCREENING_CASCADE_MULTIPLIERS[2]),
},
PriorityBudgetStage {
cap: SEED_SCREENING_UNCAPPED,
},
];
let cascade_start = std::time::Instant::now();
log::info!(
"[STAGE] {context}: seed screening cascade start seeds={} initial_cap={} stages={}",
seeds.len(),
initial_cap,
cascade_caps.len(),
);
let cascade_result = rank_indices_with_budget_cascade(
seeds.len(),
&cascade_caps,
|stage, cap, idx| {
if crate::solver::rho_optimizer::outer_wall_clock_deadline_exceeded() {
return Err(());
}
screening_cap.store(cap, Ordering::Relaxed);
obj.reset();
screening_cap.store(cap, Ordering::Relaxed);
let seed_started = std::time::Instant::now();
let result = obj.eval_screening_proxy(&seeds[idx]);
let seed_elapsed = seed_started.elapsed().as_secs_f64();
match result {
Ok(cost) if cost.is_finite() => {
log::info!(
"[STAGE] {context}: seed-screen stage={} seed={}/{} cap={} elapsed={:.3}s cost={:.6e}",
stage,
idx + 1,
seeds.len(),
if cap == 0 {
"uncapped".to_string()
} else {
cap.to_string()
},
seed_elapsed,
cost,
);
Ok(cost)
}
Ok(cost) => {
log::info!(
"[STAGE] {context}: seed-screen stage={} seed={}/{} cap={} elapsed={:.3}s cost=non-finite ({:.3e})",
stage,
idx + 1,
seeds.len(),
if cap == 0 {
"uncapped".to_string()
} else {
cap.to_string()
},
seed_elapsed,
cost,
);
Ok(cost)
}
Err(_) => {
log::info!(
"[STAGE] {context}: seed-screen stage={} seed={}/{} cap={} elapsed={:.3}s rejected (error)",
stage,
idx + 1,
seeds.len(),
if cap == 0 {
"uncapped".to_string()
} else {
cap.to_string()
},
seed_elapsed,
);
Err(())
}
}
},
|PriorityStageSummary {
stage,
cap,
ranked,
rejected,
}| {
log::info!(
"[STAGE] {context}: seed-screen stage={} cap={} elapsed={:.3}s ranked={} rejected={}",
stage,
if cap == 0 {
"uncapped".to_string()
} else {
cap.to_string()
},
cascade_start.elapsed().as_secs_f64(),
ranked,
rejected,
);
if ranked > 0 && stage > 0 {
let final_cap = if cap == 0 {
"uncapped".to_string()
} else {
cap.to_string()
};
log::info!(
"[OUTER] {context}: seed screening cap escalated from {} to {} \
(initial cap was too shallow for this problem; {}/{} seeds ranked)",
initial_cap,
final_cap,
ranked,
seeds.len(),
);
}
},
);
let rejected = cascade_result.rejected;
let final_cap_used = cascade_result.final_cap;
let stages_consumed = cascade_result.stages_consumed;
let ranked = cascade_result.ranked_indices;
screening_cap.store(previous_cap, Ordering::Relaxed);
obj.reset();
log::info!(
"[OUTER] {context}: seed screening cascade complete elapsed={:.3}s stages_used={} final_cap={} ranked={}/{}",
cascade_start.elapsed().as_secs_f64(),
stages_consumed,
if final_cap_used == 0 {
"uncapped".to_string()
} else {
final_cap_used.to_string()
},
ranked.len(),
seeds.len(),
);
if ranked.is_empty() {
log::info!(
"[OUTER] {context}: no finite seed cost even with full inner budget \
({} seeds, {} rejected, {} cascade stages tried); keeping heuristic order",
seeds.len(),
rejected,
stages_consumed,
);
return seeds.to_vec();
}
let mut ordered = Vec::with_capacity(seeds.len());
let mut seen = vec![false; seeds.len()];
for idx in ranked {
seen[idx] = true;
ordered.push(seeds[idx].clone());
}
for (idx, seed) in seeds.iter().enumerate() {
if !seen[idx] {
ordered.push(seed.clone());
}
}
let rho_dim = obj.capability().theta_layout().rho_dim();
if rho_dim > 0 && ordered.len() > 1 {
let upper: Vec<f64> = match config.bounds.as_ref() {
Some((_, hi)) => hi.to_vec(),
None => vec![config.rho_bound; rho_dim],
};
let (interior, boundary): (Vec<Array1<f64>>, Vec<Array1<f64>>) = ordered
.into_iter()
.partition(|seed| !seed_is_oversmoothing_boundary(seed, rho_dim, &upper));
if !interior.is_empty() && !boundary.is_empty() {
log::info!(
"[OUTER] {context}: demoted {} over-smoothing boundary seed(s) below {} \
interior seed(s) so the outer descent does not originate on the flat \
ρ=bound plateau",
boundary.len(),
interior.len(),
);
}
ordered = interior;
ordered.extend(boundary);
let promote_extreme_seeds = config
.seed_config
.risk_profile
.promotes_interior_seed_extremes();
if promote_extreme_seeds && ordered.len() > 1 {
let rho_sum =
|seed: &Array1<f64>| -> f64 { (0..rho_dim.min(seed.len())).map(|i| seed[i]).sum() };
if let Some((most_flexible_idx, _)) = ordered
.iter()
.enumerate()
.filter(|(_, seed)| !seed_is_oversmoothing_boundary(seed, rho_dim, &upper))
.min_by(|(_, a), (_, b)| rho_sum(a).total_cmp(&rho_sum(b)))
{
if most_flexible_idx != 0 {
let flexible = ordered.remove(most_flexible_idx);
log::info!(
"[OUTER] {context}: promoted the most-flexible interior seed \
(Σρ={:.3}) to the front so the low-λ basin gets a full-budget \
solve (capped screening systematically under-ranks it)",
rho_sum(&flexible),
);
ordered.insert(0, flexible);
}
}
if promote_extreme_seeds && ordered.len() > 2 {
let heaviest_idx = ordered
.iter()
.enumerate()
.skip(1)
.filter(|(_, seed)| !seed_is_oversmoothing_boundary(seed, rho_dim, &upper))
.max_by(|(_, a), (_, b)| rho_sum(a).total_cmp(&rho_sum(b)))
.map(|(idx, _)| idx);
if let Some(heaviest_idx) = heaviest_idx
&& heaviest_idx > 1
{
let heavy = ordered.remove(heaviest_idx);
log::info!(
"[OUTER] {context}: promoted the heaviest interior seed (Σρ={:.3}) to \
the second full-budget slot so a budget-limited non-Gaussian multi-start \
also solves the well-penalized basin (#1426: a non-separable λ→0 stall \
at slot 0 otherwise ships a non-converged full-basis overfit)",
rho_sum(&heavy),
);
ordered.insert(1, heavy);
}
}
}
}
log::debug!(
"[OUTER] {context}: seed screening ranked {}/{} candidates at cap={} \
(initial cap={}, stages used={}); rejected={}",
ordered.len() - rejected,
seeds.len(),
if final_cap_used == 0 {
"uncapped".to_string()
} else {
final_cap_used.to_string()
},
initial_cap,
stages_consumed,
rejected,
);
ordered
}
pub(crate) const OVERSMOOTH_BOUNDARY_MARGIN: f64 = 0.5;
pub(crate) fn seed_is_oversmoothing_boundary(
seed: &Array1<f64>,
rho_dim: usize,
upper: &[f64],
) -> bool {
if rho_dim == 0 || seed.len() < rho_dim {
return false;
}
(0..rho_dim).all(|i| {
let hi = upper.get(i).copied().unwrap_or(f64::INFINITY);
hi.is_finite() && seed[i] >= hi - OVERSMOOTH_BOUNDARY_MARGIN
})
}
#[inline]
pub(crate) fn candidate_improves_best(candidate: &OuterResult, best: Option<&OuterResult>) -> bool {
match best {
None => true,
Some(best) if candidate.converged != best.converged => candidate.converged,
Some(best) => candidate.final_value < best.final_value,
}
}
pub(crate) const PARSIMONY_TIE_REL_BAND: f64 = 1e-3;
#[inline]
fn smoothing_rho_sum(result: &OuterResult, rho_dim: usize) -> f64 {
(0..rho_dim.min(result.rho.len()))
.map(|i| result.rho[i])
.sum()
}
#[inline]
fn nonconverged_cost_is_trustworthy(result: &OuterResult) -> bool {
result
.final_grad_norm
.is_none_or(|g| g.is_finite() && g <= FLAT_VALLEY_STALL_GRAD_CEILING)
}
#[inline]
pub(crate) fn candidate_improves_best_parsimonious(
candidate: &OuterResult,
best: Option<&OuterResult>,
rho_dim: usize,
) -> bool {
match best {
None => true,
Some(best) if candidate.converged != best.converged => candidate.converged,
Some(best) if candidate.converged && best.converged && rho_dim > 0 => {
let scale = candidate
.final_value
.abs()
.max(best.final_value.abs())
.max(1.0);
let gap = (candidate.final_value - best.final_value).abs();
if gap <= PARSIMONY_TIE_REL_BAND * scale {
smoothing_rho_sum(candidate, rho_dim) > smoothing_rho_sum(best, rho_dim)
} else {
candidate.final_value < best.final_value
}
}
Some(best) => {
let candidate_trustworthy = nonconverged_cost_is_trustworthy(candidate);
let best_trustworthy = nonconverged_cost_is_trustworthy(best);
match (candidate_trustworthy, best_trustworthy) {
(true, false) => true,
(false, true) => false,
(true, true) => candidate.final_value < best.final_value,
(false, false) => match (candidate.final_grad_norm, best.final_grad_norm) {
(Some(cg), Some(bg)) if cg.is_finite() && bg.is_finite() => cg < bg,
_ => candidate.final_value < best.final_value,
},
}
}
}
}
#[inline]
pub(crate) fn should_stop_expensive_multistart_after_best(
best: Option<&OuterResult>,
expensive_seed_limit: Option<usize>,
quality_compare_remaining_gaussian_seeds: bool,
) -> bool {
!quality_compare_remaining_gaussian_seeds
&& expensive_seed_limit.is_some()
&& best.is_some_and(|b| {
b.final_value.is_finite()
&& !b.converged
&& matches!(
b.operator_stop_reason,
Some(OperatorTrustRegionStopReason::CostStallFlatValley)
)
&& b.final_grad_norm
.is_none_or(|g| g.is_finite() && g <= FLAT_VALLEY_STALL_GRAD_CEILING)
})
}