Skip to main content

centered_rank

Function centered_rank 

Source
pub fn centered_rank<B: Backend>(
    fitness: Tensor<B, 1>,
    device: &<B as BackendTypes>::Device,
) -> Result<Tensor<B, 1>, ShapingError>
Expand description

Returns centered ranks: the largest fitness maps to +0.5, the smallest to -0.5, with linear spacing in between.

Under the crate’s maximise convention (canonical: higher is better) this assigns the best (highest-fitness) individual the highest utility +0.5 and the worst the lowest -0.5, which is the sign a gradient-style ES update expects — no negation at the call site.

Centered ranks are standard in modern ES (e.g. OpenAI-ES) because they remove outlier fitness magnitudes and keep the signal scale-free across generations. Implemented host-side because the argsort pathway is easier to reason about; swap in a tensor-native implementation if this ever shows up on a profile.

An empty input returns an empty tensor.

§Examples

use burn::backend::Flex;
use burn::tensor::Tensor;
use rlevo_evolution::shaping::centered_rank;

let device = Default::default();
let t = Tensor::<Flex, 1>::from_floats([10.0f32, 20.0, 30.0, 40.0], &device);
let r = centered_rank(t, &device).unwrap();
let values = r.into_data().into_vec::<f32>().expect("shaped tensor must be readable as f32");
// Smallest value maps to -0.5, largest to +0.5.
assert!((values[0] - (-0.5)).abs() < 1e-6);
assert!((values[3] - 0.5).abs() < 1e-6);

§Errors

Returns ShapingError::NonFloatData if the tensor’s element data cannot be read as f32 — for example, when using a backend that stores integer-typed tensors and into_vec::<f32>() fails.