///|
pub fn scalar_grid_search(
objective : (Double) -> Double,
minimum : Double,
maximum : Double,
steps : Int,
) -> (Double, Double) {
let safe = Int::max(1, steps)
let mut best_x = minimum
let mut best_value = objective(minimum)
for i in 0..<=safe {
let fraction = Double::from_int(i) / Double::from_int(safe)
let x = lerp(minimum, maximum, fraction)
let value = objective(x)
if value < best_value {
best_x = x
best_value = value
}
}
(best_x, best_value)
}
///|
pub fn golden_section_minimize(
objective : (Double) -> Double,
minimum : Double,
maximum : Double,
iterations : Int,
) -> (Double, Double) {
let mut left = Double::min(minimum, maximum)
let mut right = Double::max(minimum, maximum)
let ratio = (5.0.sqrt() - 1.0) / 2.0
let mut x1 = right - ratio * (right - left)
let mut x2 = left + ratio * (right - left)
let mut f1 = objective(x1)
let mut f2 = objective(x2)
for _ in 0.. f2 {
left = x1
x1 = x2
f1 = f2
x2 = left + ratio * (right - left)
f2 = objective(x2)
} else {
right = x2
x2 = x1
f2 = f1
x1 = right - ratio * (right - left)
f1 = objective(x1)
}
}
let x = (left + right) / 2.0
(x, objective(x))
}
///|
pub fn scalar_maximize(
objective : (Double) -> Double,
minimum : Double,
maximum : Double,
iterations : Int,
) -> (Double, Double) {
let result = golden_section_minimize(
fn(value) { -objective(value) },
minimum,
maximum,
iterations,
)
(result.0, -result.1)
}
///|
pub fn weighted_linear_fit(
x : ArrayView[Double],
y : ArrayView[Double],
weights : ArrayView[Double],
) -> LeastSquaresResult {
let count = Int::min(x.length(), Int::min(y.length(), weights.length()))
let mut sum_w = 0.0
let mut sum_x = 0.0
let mut sum_y = 0.0
let mut sum_xx = 0.0
let mut sum_xy = 0.0
for i in 0.. LeastSquaresResult {
let count = Int::min(x.length(), y.length())
let weights : Array[Double] = []
for _ in 0.. LeastSquaresResult {
let count = Int::min(observed.length(), reference.length())
let weights : Array[Double] = []
for _ in 0.. Double {
let count = Int::min(observed.length(), predicted.length())
let errors : Array[Double] = []
for i in 0.. Double {
let count = Int::min(observed.length(), predicted.length())
let mut total = 0.0
for i in 0.. Double,
) -> Array[(Double, Double)] {
let output : Array[(Double, Double)] = []
for value in values {
output.push((value, objective(value)))
}
output
}
///|
pub fn best_parameter(
results : ArrayView[(Double, Double)],
) -> (Double, Double)? {
if results.length() == 0 {
None
} else {
let mut best = results[0]
for result in results[1:] {
if result.1 < best.1 {
best = result
}
}
Some(best)
}
}
///|
pub fn residual_summary(
observed : ArrayView[Double],
predicted : ArrayView[Double],
) -> Summary {
let count = Int::min(observed.length(), predicted.length())
let residuals : Array[Double] = []
for i in 0.. Array[Double] {
let safe = Double::max(0.0, penalty)
coefficients.map(fn(value) { value / (1.0 + safe) })
}
///|
pub fn finite_objective(
values : ArrayView[Double],
objective : (Double) -> Double,
) -> Double {
let mut best = 0.0 / 0.0
for value in values {
let candidate = objective(value)
if is_finite(candidate) && (!is_finite(best) || candidate < best) {
best = candidate
}
}
best
}