use serde::{Deserialize, Serialize};
use crate::iteration::comprehension::ast::Comprehension;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum RuleId {
R0a,
R0b,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReducibilityFinding {
pub reduction: Option<Reduction>,
pub rule: Option<RuleId>,
pub improvement: ComplexityDelta,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Reduction {
Replace { with: Comprehension },
Rewrite { rule: RuleId, witness: Comprehension },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ComplexityDelta {
pub compute_order: Ordering,
pub memory_order: Ordering,
pub rationale: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Ordering {
Less,
Equal,
Greater,
}
impl ComplexityDelta {
pub fn less_compute() -> Self {
Self {
compute_order: Ordering::Less,
memory_order: Ordering::Equal,
rationale: "strictly less compute",
}
}
pub fn less_memory() -> Self {
Self {
compute_order: Ordering::Equal,
memory_order: Ordering::Less,
rationale: "strictly less memory",
}
}
pub fn less_both() -> Self {
Self {
compute_order: Ordering::Less,
memory_order: Ordering::Less,
rationale: "strictly less compute and memory",
}
}
pub fn equal() -> Self {
Self {
compute_order: Ordering::Equal,
memory_order: Ordering::Equal,
rationale: "no asymptotic change",
}
}
pub fn is_strict_improvement(&self) -> bool {
matches!(
(self.compute_order, self.memory_order),
(Ordering::Less, Ordering::Less)
| (Ordering::Less, Ordering::Equal)
| (Ordering::Equal, Ordering::Less)
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn delta_strict_improvement_classifier() {
assert!(ComplexityDelta::less_compute().is_strict_improvement());
assert!(ComplexityDelta::less_memory().is_strict_improvement());
assert!(ComplexityDelta::less_both().is_strict_improvement());
assert!(!ComplexityDelta::equal().is_strict_improvement());
}
#[test]
fn rule_id_round_trip_serde() {
let r = RuleId::R5;
let json = serde_json::to_string(&r).unwrap();
let back: RuleId = serde_json::from_str(&json).unwrap();
assert_eq!(r, back);
}
}