///|
/// Geometric step schedule for deterministic calibration refinement.
pub fn calibration_step_schedule(
initial~ : Double,
decay~ : Double,
count~ : Int,
) -> Array[Double] {
let result : Array[Double] = []
let mut step = initial.abs()
let factor = decay.max(0.0).min(1.0)
for _ in 0.. Array[Double] {
calibration_step_schedule(initial~, decay=cooling, count~)
}
///|
pub fn calibration_iteration_budget(
levels : Int,
iterations_per_level : Int,
) -> Int {
levels.max(0) * iterations_per_level.max(0)
}
///|
pub fn calibration_level_of_iteration(
iteration : Int,
iterations_per_level : Int,
levels : Int,
) -> Int {
if iterations_per_level <= 0 || levels <= 0 {
0
} else {
(iteration.max(0) / iterations_per_level).min(levels - 1)
}
}
///|
pub fn calibration_progress(iteration : Int, total : Int) -> Double {
if total <= 0 {
0.0
} else {
iteration.max(0).min(total).to_double() / total.to_double()
}
}
///|
pub fn calibration_should_stop(
iteration : Int,
total : Int,
loss : Double,
target : Double,
) -> Bool {
iteration >= total || loss <= target
}
///|
pub fn calibration_loss_delta(previous : Double, current : Double) -> Double {
previous - current
}
///|
pub fn calibration_improvement_ratio(
previous : Double,
current : Double,
) -> Double {
if previous.abs() <= 0.000000000001 {
0.0
} else {
(previous - current) / previous.abs()
}
}
///|
pub fn calibration_has_converged(
losses : ArrayView[Double],
tolerance : Double,
window : Int,
) -> Bool {
if losses.length() < 2 || window <= 0 || losses.length() < window + 1 {
false
} else {
let start = losses.length() - window - 1
let improvement = losses[start] - losses[losses.length() - 1]
improvement.abs() <= tolerance
}
}
///|
pub fn calibration_best_loss(losses : ArrayView[Double]) -> Double {
if losses.length() == 0 {
0.0
} else {
let mut result = losses[0]
for loss in losses {
result = result.min(loss)
}
result
}
}
///|
pub fn calibration_loss_history_append(
history : Array[Double],
loss : Double,
capacity : Int,
) -> Unit {
history.push(loss)
if capacity > 0 {
while history.length() > capacity {
let _ = history.remove(0)
}
}
}