use crate::conformance::{FitnessConst, PrecisionConst};
use crate::law::{IsTrue, Require};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MoveCategory {
LogOnly,
ModelOnly,
SyncMove,
}
pub struct DeltaReport<
const FIT_NUM: u64,
const FIT_DEN: u64,
const PREC_NUM: u64,
const PREC_DEN: u64,
> where
Require<{ FIT_DEN > 0 }>: IsTrue,
Require<{ FIT_NUM <= FIT_DEN }>: IsTrue,
Require<{ PREC_DEN > 0 }>: IsTrue,
Require<{ PREC_NUM <= PREC_DEN }>: IsTrue,
{
pub total_log_only_moves: u64,
pub total_model_only_moves: u64,
pub total_sync_moves: u64,
pub fitness: FitnessConst<FIT_NUM, FIT_DEN>,
pub precision: PrecisionConst<PREC_NUM, PREC_DEN>,
}
impl<const FIT_NUM: u64, const FIT_DEN: u64, const PREC_NUM: u64, const PREC_DEN: u64>
std::fmt::Display for DeltaReport<FIT_NUM, FIT_DEN, PREC_NUM, PREC_DEN>
where
Require<{ FIT_DEN > 0 }>: IsTrue,
Require<{ FIT_NUM <= FIT_DEN }>: IsTrue,
Require<{ PREC_DEN > 0 }>: IsTrue,
Require<{ PREC_NUM <= PREC_DEN }>: IsTrue,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"DeltaReport: log-only={}, model-only={}, sync={}",
self.total_log_only_moves, self.total_model_only_moves, self.total_sync_moves
)
}
}
pub struct DriftMonitor<const ALPHA_NUM: u64, const ALPHA_DEN: u64>
where
Require<{ ALPHA_DEN > 0 }>: IsTrue,
Require<{ ALPHA_NUM <= ALPHA_DEN }>: IsTrue,
{
pub drift_detected: bool,
pub significance_threshold: f64,
}
impl<const ALPHA_NUM: u64, const ALPHA_DEN: u64> DriftMonitor<ALPHA_NUM, ALPHA_DEN>
where
Require<{ ALPHA_DEN > 0 }>: IsTrue,
Require<{ ALPHA_NUM <= ALPHA_DEN }>: IsTrue,
{
pub fn new() -> Self {
Self {
drift_detected: false,
significance_threshold: ALPHA_NUM as f64 / ALPHA_DEN as f64,
}
}
}
impl<const ALPHA_NUM: u64, const ALPHA_DEN: u64> Default for DriftMonitor<ALPHA_NUM, ALPHA_DEN>
where
Require<{ ALPHA_DEN > 0 }>: IsTrue,
Require<{ ALPHA_NUM <= ALPHA_DEN }>: IsTrue,
{
fn default() -> Self {
Self::new()
}
}
pub struct DriftWitness<
const ALPHA_NUM: u64,
const ALPHA_DEN: u64,
const CHANGE_POINT: usize,
W: crate::witness::Witness,
> where
Require<{ ALPHA_DEN > 0 }>: IsTrue,
Require<{ ALPHA_NUM <= ALPHA_DEN }>: IsTrue,
{
pub significance: crate::law::Between01<ALPHA_NUM, ALPHA_DEN>,
pub change_point: usize,
pub _witness: core::marker::PhantomData<W>,
}
impl<
const ALPHA_NUM: u64,
const ALPHA_DEN: u64,
const CHANGE_POINT: usize,
W: crate::witness::Witness,
> DriftWitness<ALPHA_NUM, ALPHA_DEN, CHANGE_POINT, W>
where
Require<{ ALPHA_DEN > 0 }>: IsTrue,
Require<{ ALPHA_NUM <= ALPHA_DEN }>: IsTrue,
{
pub fn new(change_point: usize) -> Self {
Self {
significance: crate::law::Between01::new(),
change_point,
_witness: core::marker::PhantomData,
}
}
}
pub fn enforce_prediction_horizon_before_drift<
const HORIZON_STEPS: usize,
const CHANGE_POINT: usize,
>()
where
Require<{ HORIZON_STEPS <= CHANGE_POINT }>: IsTrue,
{
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DriftKind {
Sudden,
Gradual,
Incremental,
Recurring,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DriftClaim {
pub kind: DriftKind,
pub change_points: Vec<usize>,
pub process_ref: String,
}
impl DriftClaim {
#[must_use]
pub fn new(kind: DriftKind, change_points: Vec<usize>, process_ref: impl Into<String>) -> Self {
Self {
kind,
change_points,
process_ref: process_ref.into(),
}
}
#[must_use]
pub fn is_grounded(&self) -> bool {
!self.process_ref.trim().is_empty() && !self.change_points.is_empty()
}
#[must_use = "check the admission result"]
pub fn admit_flat(&self) -> Result<(), DriftRefusal> {
if self.process_ref.trim().is_empty() {
return Err(DriftRefusal::UngroundedDrift);
}
if self.change_points.is_empty() {
return Err(DriftRefusal::NoChangePointsClaimed);
}
if matches!(self.kind, DriftKind::Sudden) && self.change_points.len() != 1 {
return Err(DriftRefusal::SuddenDriftMultiplePoints);
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DriftRefusal {
UngroundedDrift,
NoChangePointsClaimed,
SuddenDriftMultiplePoints,
}
impl core::fmt::Display for DriftRefusal {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let law = match self {
DriftRefusal::UngroundedDrift => "UngroundedDrift",
DriftRefusal::NoChangePointsClaimed => "NoChangePointsClaimed",
DriftRefusal::SuddenDriftMultiplePoints => "SuddenDriftMultiplePoints",
};
write!(f, "drift refusal: {law}")
}
}