shark/fish/src/eval.rs

68 lines
1.8 KiB
Rust

use mino::Mat;
mod basic;
mod downstacking;
pub use basic::{i_deps, max_height, row_trans};
pub use downstacking::mystery_mdse;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Features(pub usize, pub [i32; 4]);
/// Computes the feature vector for the given matrix. These are the underlying values
/// used to calculate the heuristic rating.
pub fn features(mat: &Mat, pcnt: usize) -> Features {
Features(
pcnt,
[
max_height(mat),
i_deps(mat),
row_trans(mat),
mystery_mdse(mat),
],
)
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Weights(pub [i32; 4]);
impl Weights {
/// Default weights (determined experimentally).
pub const DEFAULT: Self = Self([
512, // max_height
1024, // i_deps
0, // FIXME: row_trans
1024, // mdse
]);
/// Constant penalty given to the number of pieces placed. Each element of the weight
/// vector is effectively a ratio to this constant, i.e. if this were to be doubled,
/// then all of the weights should be doubled as well to produce an identical
/// heuristic.
pub const PER_PIECE: i32 = 1024;
}
impl Default for Weights {
fn default() -> Self {
Self::DEFAULT
}
}
impl Features {
/// Applies the given weights vector to the features. Returns the heuristic score.
#[inline]
pub fn evaluate(&self, weights: &Weights) -> i32 {
let pcnt = self.0 as i32;
let ft = &self.1;
let wt = &weights.0;
let mut score = Weights::PER_PIECE * pcnt;
score += wt[0] * ft[0];
score += wt[1] * ft[1];
score += wt[2] * ft[2];
score += wt[3] * ft[3];
// TODO(?) quadratic weights, e.g. score += wt[i] * f[j]^2
score
}
}