Skip to content
Merged
2 changes: 1 addition & 1 deletion benches/linalg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main};

#[path = "../src"]
#[allow(dead_code, unused_imports)]
#[expect(dead_code, unused_imports)]
mod source {
pub mod linalg;
}
Expand Down
2 changes: 1 addition & 1 deletion python/src/fitness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ fn values_with_gradients(
// whether `object` is referenced by the caller only: Python kept no reference to it. (pyo3
// deprecates `get_refcnt` for `ffi::Py_REFCNT`, which is unsafe, and this crate has no unsafe
// code.)
#[allow(deprecated)]
#[expect(deprecated)]
fn only_reference(object: &Bound<'_, PyAny>) -> bool {
object.get_refcnt() == 1
}
Expand Down
2 changes: 1 addition & 1 deletion python/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl PyGaussianProcess {
}

/// The posterior mean and variance at `point`, with their gradients.
#[allow(clippy::type_complexity)]
#[expect(clippy::type_complexity)]
fn predict_with_gradient<'py>(
&self,
py: Python<'py>,
Expand Down
2 changes: 1 addition & 1 deletion python/src/problems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ fn check_wfg(
if distance == 0 {
return Err(format!("{name} needs at least 1 distance parameter"));
}
if even && distance % 2 == 1 {
if even && !distance.is_multiple_of(2) {
return Err(format!(
"{name} needs an even number of distance parameters, not {distance}"
));
Expand Down
6 changes: 3 additions & 3 deletions python/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ type Result<T> = std::result::Result<T, String>;
/// stage did and its last point. Returns the result as a dict.
#[pyfunction]
#[pyo3(signature = (config, fitness, batch = false, parallel = false, on_generation = None, problem = None, control = None, checkpoint = None, checkpoint_every = None, resume = None, gradient = None, combined_gradient = false, constraints = 0, on_stage = None, on_stage_finished = None))]
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
pub fn run<'py>(
py: Python<'py>,
config: &str,
Expand Down Expand Up @@ -1101,7 +1101,7 @@ fn real_algorithm<'py>(
}

// a gradient method, built from its settings: once per run, its size doesn't matter
#[allow(clippy::large_enum_variant)]
#[expect(clippy::large_enum_variant)]
enum GradientMethod {
FirstOrder(FirstOrder),
Lbfgsb(Lbfgsb),
Expand Down Expand Up @@ -1275,7 +1275,7 @@ fn gradient_method(
}

// OpenAI's evolution strategy, with its settings
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
fn build_open_es(
real: Real,
population_size: usize,
Expand Down
1 change: 0 additions & 1 deletion python/src/trees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,6 @@ impl PyTree {
hasher.finish()
}

#[allow(clippy::type_complexity)]
fn __reduce__<'py>(&self, py: Python<'py>) -> PyResult<(Bound<'py, PyAny>, (String, String))> {
let load = py.get_type::<PyTree>().getattr("_from_json")?;
let set = serde_json::to_string(self.set.as_ref())
Expand Down
2 changes: 1 addition & 1 deletion src/algorithm/bo/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! with their genes rounded inside the kernel.

// the sealed trait's methods take the crate's own unit-cube map: unnameable outside the crate
#![allow(private_interfaces)]
#![expect(private_interfaces)]

use crate::genome::{Integer, Integers, Real, Reals, Representation};
use crate::model::gp::Scaling;
Expand Down
6 changes: 3 additions & 3 deletions src/algorithm/cmaes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,9 +1147,9 @@ mod tests {
}

fn rosenbrock(x: &Reals) -> f64 {
x.windows(2)
.map(|w| {
let (a, b) = (w[1] - w[0] * w[0], 1.0 - w[0]);
x.array_windows()
.map(|&[xi, next]| {
let (a, b) = (next - xi * xi, 1.0 - xi);
100.0 * a * a + b * b
})
.sum()
Expand Down
6 changes: 3 additions & 3 deletions src/algorithm/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2765,9 +2765,9 @@ mod tests {

// the Rosenbrock function with only +, − and ×, which is the same on every platform
fn rosenbrock(x: &Reals) -> f64 {
x.windows(2)
.map(|w| {
let (a, b) = (w[1] - w[0] * w[0], 1.0 - w[0]);
x.array_windows()
.map(|&[xi, next]| {
let (a, b) = (next - xi * xi, 1.0 - xi);
100.0 * a * a + b * b
})
.sum()
Expand Down
6 changes: 3 additions & 3 deletions src/algorithm/es.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,9 +1139,9 @@ mod tests {

// the Rosenbrock function with only +, − and ×, which is the same on every platform
fn rosenbrock(x: &Reals) -> f64 {
x.windows(2)
.map(|w| {
let (a, b) = (w[1] - w[0] * w[0], 1.0 - w[0]);
x.array_windows()
.map(|&[xi, next]| {
let (a, b) = (next - xi * xi, 1.0 - xi);
100.0 * a * a + b * b
})
.sum()
Expand Down
8 changes: 4 additions & 4 deletions src/algorithm/ga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ where
) {
let end = offspring.len() + wanted;
// `as_chunks` measured a few instructions more per generation on real-valued genomes
#[allow(clippy::chunks_exact_to_as_chunks)]
#[expect(clippy::chunks_exact_to_as_chunks)]
for pair in parents.chunks_exact(2) {
let parents = [&self.population[pair[0]], &self.population[pair[1]]];
let mut a = spare.copy(parents[0].genome());
Expand Down Expand Up @@ -1721,9 +1721,9 @@ mod tests {
generations: u64,
) -> (Population<Reals>, Option<Individual<Reals>>, u64) {
let rosenbrock = |x: &Reals| {
x.windows(2)
.map(|w| {
let (a, b) = (w[1] - w[0] * w[0], 1.0 - w[0]);
x.array_windows()
.map(|&[xi, next]| {
let (a, b) = (next - xi * xi, 1.0 - xi);
100.0 * a * a + b * b
})
.sum::<f64>()
Expand Down
35 changes: 23 additions & 12 deletions src/algorithm/lbfgsb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl Lbfgsb {
/// current run, never [`Gradients::Auto`]. Before a run, as an ask without an engine would
/// resolve it: forward differences for `Auto`.
// the setting resolved, not the setting itself
#[allow(clippy::misnamed_getters)]
#[expect(clippy::misnamed_getters)]
pub fn gradients(&self) -> Gradients {
self.resolved
}
Expand Down Expand Up @@ -426,9 +426,11 @@ impl Lbfgsb {
if alpha == 1.0 {
point.copy_from_slice(&self.target);
} else {
// resliced to n: no bounds checks in the loop
let (point, x, direction) = (&mut point[..n], &x[..n], &self.direction[..n]);
let (lower, upper) = (&self.lower[..n], &self.upper[..n]);
for i in 0..n {
point[i] =
(x[i] + alpha * self.direction[i]).clamp(self.lower[i], self.upper[i]);
point[i] = (x[i] + alpha * direction[i]).clamp(lower[i], upper[i]);
}
}
}
Expand Down Expand Up @@ -573,11 +575,14 @@ impl Lbfgsb {
&mut self.target,
)
.ok()?;
let n = x.len();
let (target, gradient) = (&self.target[..n], &self.gradient[..n]);
let direction = &mut self.direction[..n];
let mut slope = 0.0;
for i in 0..x.len() {
let d = self.target[i] - x[i];
self.direction[i] = d;
slope += self.gradient[i] * d;
for i in 0..n {
let d = target[i] - x[i];
direction[i] = d;
slope += gradient[i] * d;
}
(slope < 0.0 && slope.is_finite()).then_some(slope)
}
Expand All @@ -588,13 +593,16 @@ impl Lbfgsb {
let max_step = if self.first_iteration {
1.0
} else {
let n = x.len();
let (direction, lower, upper) =
(&self.direction[..n], &self.lower[..n], &self.upper[..n]);
let mut max_step = f64::MAX;
for i in 0..x.len() {
let d = self.direction[i];
for i in 0..n {
let d = direction[i];
let room = if d > 0.0 {
(self.upper[i] - x[i]) / d
(upper[i] - x[i]) / d
} else if d < 0.0 {
(self.lower[i] - x[i]) / d
(lower[i] - x[i]) / d
} else {
continue;
};
Expand Down Expand Up @@ -789,10 +797,13 @@ impl Lbfgsb {

// ‖P(x − g) − x‖∞: the largest move of a projected steepest descent step of length 1
fn projected_gradient(x: &[f64], g: &[f64], lower: &[f64], upper: &[f64]) -> f64 {
let n = x.len();
let (g, lower, upper) = (&g[..n], &lower[..n], &upper[..n]);
let mut largest = 0.0f64;
for i in 0..x.len() {
for i in 0..n {
let moved = (x[i] - g[i]).clamp(lower[i], upper[i]) - x[i];
if moved.is_nan() {
std::hint::cold_path();
return f64::NAN;
}
largest = largest.max(moved.abs());
Expand Down
11 changes: 8 additions & 3 deletions src/algorithm/lbfgsb/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ impl Memory {
epsilon: f64,
) -> bool {
// sᵀy and yᵀy first, from the vectors: a skipped pair overwrites nothing
let n = self.n;
let (x_new, x_old, g_new, g_old) = (&x_new[..n], &x_old[..n], &g_new[..n], &g_old[..n]);
let (mut sty, mut yty) = (0.0, 0.0);
for i in 0..self.n {
for i in 0..n {
let (s, y) = (x_new[i] - x_old[i], g_new[i] - g_old[i]);
sty += s * y;
yty += y * y;
Expand Down Expand Up @@ -423,7 +425,7 @@ impl Workspace {
/// `upper`], by Algorithm CP of Byrd et al. (section 4), with the middle matrix factored.
/// Afterwards `self.c` = Wᵀ(xc − x) (eq. 4.13) and `self.active` marks the genes held at a
/// bound: those whose breakpoint the path passed or was at (tᵢ = 0), and the `fixed` ones.
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
pub(super) fn cauchy_point(
&mut self,
memory: &Memory,
Expand All @@ -435,6 +437,7 @@ impl Workspace {
xc: &mut [f64],
) {
let n = x.len();
let (g, lower, upper, fixed) = (&g[..n], &lower[..n], &upper[..n], &fixed[..n]);
let len = memory.len();
let theta = memory.theta();
let d = resized(&mut self.d, n);
Expand Down Expand Up @@ -542,6 +545,7 @@ impl Workspace {
}
let dt_min = if dt_min > 0.0 { dt_min } else { 0.0 };
let t = t_old + dt_min;
let xc = &mut xc[..n];
for i in 0..n {
if d[i] != 0.0 {
xc[i] = (x[i] + t * d[i]).clamp(lower[i], upper[i]);
Expand All @@ -557,7 +561,7 @@ impl Workspace {
/// section 5.1), projected into the box (Morales and Nocedal, 2011), into `xbar`. If the
/// projection isn't a descent direction from `x`, the step towards x̂ truncated at the box
/// instead (eq. 5.8, 5.9).
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
pub(super) fn subspace_step(
&mut self,
memory: &Memory,
Expand Down Expand Up @@ -618,6 +622,7 @@ impl Workspace {
if clipped {
// the projection, if it's a descent direction (the authors' implementation reverts
// when (x̄ − x)ᵀg > 0)
let (xbar, g) = (&mut xbar[..n], &g[..n]);
let mut slope = 0.0;
for i in 0..n {
slope += (xbar[i] - x[i]) * g[i];
Expand Down
6 changes: 3 additions & 3 deletions src/algorithm/line_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl Settings {
/// For nonlinear conjugate gradients: as [`QUASI_NEWTON`](Settings::QUASI_NEWTON), with
/// η = 0.1 (Nocedal and Wright, 2006, section 3.1).
// for nonlinear conjugate gradients (batch D1 of docs/optimization-plan.md)
#[allow(dead_code)]
#[cfg_attr(not(test), expect(dead_code))]
pub(crate) const CONJUGATE_GRADIENT: Settings = Settings {
gtol: 0.1,
..Settings::QUASI_NEWTON
Expand Down Expand Up @@ -341,7 +341,7 @@ impl MoreThuente {
}

/// The step to evaluate next, or `None` once the search has stopped.
#[cfg_attr(not(test), allow(dead_code))]
#[cfg_attr(not(test), expect(dead_code))]
pub(crate) fn next(&self) -> Option<f64> {
match self.stopped {
None => Some(self.trial),
Expand All @@ -350,7 +350,7 @@ impl MoreThuente {
}

/// The number of steps told so far.
#[cfg_attr(not(test), allow(dead_code))]
#[cfg_attr(not(test), expect(dead_code))]
pub(crate) fn trials(&self) -> usize {
self.trials
}
Expand Down
1 change: 1 addition & 0 deletions src/algorithm/nelder_mead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ fn mirror(x: f64, low: f64, high: f64) -> f64 {
x
};
if mirrored.is_nan() {
std::hint::cold_path();
low
} else {
mirrored.clamp(low, high)
Expand Down
2 changes: 1 addition & 1 deletion src/algorithm/open_es.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ impl OpenEsBuilder {
setting: "population_size",
})?;
let invalid = |setting, reason: String| Err(Error::InvalidSetting { setting, reason });
if size < 2 || size % 2 != 0 {
if size < 2 || !size.is_multiple_of(2) {
return invalid(
"population_size",
format!("must be even and at least 2 (mirrored pairs), got {size}"),
Expand Down
2 changes: 1 addition & 1 deletion src/algorithm/steady.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ impl Hasher for Prehashed {
const ATTEMPTS: usize = 100;

impl<R: Representation, S, C, M> SteadyGa<R, S, C, M> {
#[allow(clippy::too_many_arguments)]
#[expect(clippy::too_many_arguments)]
pub(crate) fn new(
representation: R,
select: S,
Expand Down
7 changes: 3 additions & 4 deletions src/bin/genoxide/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ pub const FUNCTIONS: &[Function] = &[
description: "real: Rosenbrock's function (minimize, 0 at all ones)",
score: |x| {
vec![
x.windows(2)
.map(|pair| {
100.0 * math::powi(pair[1] - pair[0] * pair[0], 2)
+ math::powi(1.0 - pair[0], 2)
x.array_windows()
.map(|&[xi, next]| {
100.0 * math::powi(next - xi * xi, 2) + math::powi(1.0 - xi, 2)
})
.sum(),
]
Expand Down
Loading
Loading