use core::marker::PhantomData;
use crate::law::{IsTrue, QualityMetricKind, Require};
pub struct Metric<const KIND: QualityMetricKind, const NUM: u64, const DEN: u64>
where
Require<{ DEN > 0 }>: IsTrue,
Require<{ NUM <= DEN }>: IsTrue,
{
_private: (),
}
impl<const KIND: QualityMetricKind, const NUM: u64, const DEN: u64> Default
for Metric<KIND, NUM, DEN>
where
Require<{ DEN > 0 }>: IsTrue,
Require<{ NUM <= DEN }>: IsTrue,
{
fn default() -> Self {
Self::new()
}
}
impl<const KIND: QualityMetricKind, const NUM: u64, const DEN: u64> Metric<KIND, NUM, DEN>
where
Require<{ DEN > 0 }>: IsTrue,
Require<{ NUM <= DEN }>: IsTrue,
{
pub const fn new() -> Self {
Metric { _private: () }
}
pub const fn num(&self) -> u64 {
NUM
}
pub const fn den(&self) -> u64 {
DEN
}
}
pub type FitnessConst<const NUM: u64, const DEN: u64> =
Metric<{ QualityMetricKind::Fitness }, NUM, DEN>;
pub type PrecisionConst<const NUM: u64, const DEN: u64> =
Metric<{ QualityMetricKind::Precision }, NUM, DEN>;
pub type F1Const<const NUM: u64, const DEN: u64> = Metric<{ QualityMetricKind::F1 }, NUM, DEN>;
pub type GeneralizationConst<const NUM: u64, const DEN: u64> =
Metric<{ QualityMetricKind::Generalization }, NUM, DEN>;
pub type SimplicityConst<const NUM: u64, const DEN: u64> =
Metric<{ QualityMetricKind::Simplicity }, NUM, DEN>;
#[allow(clippy::type_complexity)]
pub struct QualityProfile<
const FN: u64,
const FD: u64,
const PN: u64,
const PD: u64,
const EN: u64,
const ED: u64,
const GN: u64,
const GD: u64,
const SN: u64,
const SD: u64,
> where
Require<{ FD > 0 }>: IsTrue,
Require<{ FN <= FD }>: IsTrue,
Require<{ PD > 0 }>: IsTrue,
Require<{ PN <= PD }>: IsTrue,
Require<{ ED > 0 }>: IsTrue,
Require<{ EN <= ED }>: IsTrue,
Require<{ GD > 0 }>: IsTrue,
Require<{ GN <= GD }>: IsTrue,
Require<{ SD > 0 }>: IsTrue,
Require<{ SN <= SD }>: IsTrue,
{
pub fitness: FitnessConst<FN, FD>,
pub precision: PrecisionConst<PN, PD>,
pub f1: F1Const<EN, ED>,
pub generalization: GeneralizationConst<GN, GD>,
pub simplicity: SimplicityConst<SN, SD>,
}
impl<
const FN: u64,
const FD: u64,
const PN: u64,
const PD: u64,
const EN: u64,
const ED: u64,
const GN: u64,
const GD: u64,
const SN: u64,
const SD: u64,
> QualityProfile<FN, FD, PN, PD, EN, ED, GN, GD, SN, SD>
where
Require<{ FD > 0 }>: IsTrue,
Require<{ FN <= FD }>: IsTrue,
Require<{ PD > 0 }>: IsTrue,
Require<{ PN <= PD }>: IsTrue,
Require<{ ED > 0 }>: IsTrue,
Require<{ EN <= ED }>: IsTrue,
Require<{ GD > 0 }>: IsTrue,
Require<{ GN <= GD }>: IsTrue,
Require<{ SD > 0 }>: IsTrue,
Require<{ SN <= SD }>: IsTrue,
{
pub const fn new() -> Self {
Self {
fitness: Metric::new(),
precision: Metric::new(),
f1: Metric::new(),
generalization: Metric::new(),
simplicity: Metric::new(),
}
}
}
impl<
const FN: u64,
const FD: u64,
const PN: u64,
const PD: u64,
const EN: u64,
const ED: u64,
const GN: u64,
const GD: u64,
const SN: u64,
const SD: u64,
> Default for QualityProfile<FN, FD, PN, PD, EN, ED, GN, GD, SN, SD>
where
Require<{ FD > 0 }>: IsTrue,
Require<{ FN <= FD }>: IsTrue,
Require<{ PD > 0 }>: IsTrue,
Require<{ PN <= PD }>: IsTrue,
Require<{ ED > 0 }>: IsTrue,
Require<{ EN <= ED }>: IsTrue,
Require<{ GD > 0 }>: IsTrue,
Require<{ GN <= GD }>: IsTrue,
Require<{ SD > 0 }>: IsTrue,
Require<{ SN <= SD }>: IsTrue,
{
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum QualityDimension {
Fitness,
Precision,
F1,
Generalization,
Simplicity,
}
impl core::fmt::Display for QualityDimension {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let name = match self {
QualityDimension::Fitness => "fitness",
QualityDimension::Precision => "precision",
QualityDimension::F1 => "f1",
QualityDimension::Generalization => "generalization",
QualityDimension::Simplicity => "simplicity",
};
write!(f, "{name}")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct SyncMove;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct LogOnlyMove;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct ModelOnlyMove;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Fitness(f64);
impl Fitness {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
if value.is_finite() && (0.0..=1.0).contains(&value) {
Some(Self(value))
} else {
None
}
}
pub fn get(self) -> f64 {
self.0
}
}
impl core::fmt::Display for Fitness {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:.2}%", self.0 * 100.0)
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Precision(f64);
impl Precision {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
if value.is_finite() && (0.0..=1.0).contains(&value) {
Some(Self(value))
} else {
None
}
}
pub fn get(self) -> f64 {
self.0
}
}
impl core::fmt::Display for Precision {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:.2}%", self.0 * 100.0)
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct F1(f64);
impl F1 {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
if value.is_finite() && (0.0..=1.0).contains(&value) {
Some(Self(value))
} else {
None
}
}
pub fn get(self) -> f64 {
self.0
}
}
impl core::fmt::Display for F1 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:.2}%", self.0 * 100.0)
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Generalization(f64);
impl Generalization {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
if value.is_finite() && (0.0..=1.0).contains(&value) {
Some(Self(value))
} else {
None
}
}
pub fn get(self) -> f64 {
self.0
}
}
impl core::fmt::Display for Generalization {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:.2}%", self.0 * 100.0)
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Simplicity(f64);
impl Simplicity {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
if value.is_finite() && (0.0..=1.0).contains(&value) {
Some(Self(value))
} else {
None
}
}
pub fn get(self) -> f64 {
self.0
}
}
impl core::fmt::Display for Simplicity {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:.2}%", self.0 * 100.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Deviation<M = ()> {
pub position: usize,
pub label: String,
pub witness: PhantomData<M>,
}
impl<M> Deviation<M> {
pub fn new(position: usize, label: impl Into<String>) -> Self {
Self {
position,
label: label.into(),
witness: PhantomData,
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ConformanceVerdict {
pub fitness: Option<Fitness>,
pub precision: Option<Precision>,
pub f1: Option<F1>,
pub generalization: Option<Generalization>,
pub simplicity: Option<Simplicity>,
pub deviations: Vec<Deviation>,
}
impl ConformanceVerdict {
pub fn new() -> Self {
Self::default()
}
pub fn is_perfect(&self) -> bool {
self.deviations.is_empty() && matches!(self.fitness, Some(f) if f.get() == 1.0)
}
}
impl core::fmt::Display for ConformanceVerdict {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fn fmt_score<T: core::fmt::Display>(
f: &mut core::fmt::Formatter<'_>,
label: &str,
slot: &Option<T>,
) -> core::fmt::Result {
match slot {
Some(v) => write!(f, "{label}={v}"),
None => write!(f, "{label}=\u{2014}"),
}
}
fmt_score(f, "fitness", &self.fitness)?;
f.write_str(" ")?;
fmt_score(f, "precision", &self.precision)?;
f.write_str(" ")?;
fmt_score(f, "f1", &self.f1)?;
f.write_str(" ")?;
fmt_score(f, "generalization", &self.generalization)?;
f.write_str(" ")?;
fmt_score(f, "simplicity", &self.simplicity)?;
write!(f, " deviations={}", self.deviations.len())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ConformanceRefusal {
MissingLog,
MissingModel,
MissingDeviationPath,
FitnessUnavailable,
PrecisionUnavailable,
F1Unavailable,
GeneralizationUnavailable,
SimplicityUnavailable,
}
impl core::fmt::Display for ConformanceRefusal {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let law = match self {
ConformanceRefusal::MissingLog => "MissingLog",
ConformanceRefusal::MissingModel => "MissingModel",
ConformanceRefusal::MissingDeviationPath => "MissingDeviationPath",
ConformanceRefusal::FitnessUnavailable => "FitnessUnavailable",
ConformanceRefusal::PrecisionUnavailable => "PrecisionUnavailable",
ConformanceRefusal::F1Unavailable => "F1Unavailable",
ConformanceRefusal::GeneralizationUnavailable => "GeneralizationUnavailable",
ConformanceRefusal::SimplicityUnavailable => "SimplicityUnavailable",
};
write!(f, "conformance verdict refused: {law}")
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct TokenReplayResult {
pub fitness: f64,
pub produced_tokens: usize,
pub consumed_tokens: usize,
pub missing_tokens: usize,
pub remaining_tokens: usize,
}