use std::collections::HashMap;
use std::marker::PhantomData;
use crate::category::entity::Entity;
pub trait ContextDef {
type Entity: Entity;
type Signal: Entity;
type Resolution: Entity;
fn resolutions() -> Vec<(Self::Entity, Self::Signal, Self::Resolution)>;
}
pub fn resolve<T: ContextDef>(entity: &T::Entity, signal: &T::Signal) -> Option<T::Resolution> {
T::resolutions()
.into_iter()
.find(|(e, s, _)| e == entity && s == signal)
.map(|(_, _, r)| r)
}
pub fn interpretations<T: ContextDef>(entity: &T::Entity) -> Vec<(T::Signal, T::Resolution)> {
T::resolutions()
.into_iter()
.filter(|(e, _, _)| e == entity)
.map(|(_, s, r)| (s, r))
.collect()
}
pub fn signals_for<T: ContextDef>(entity: &T::Entity) -> Vec<T::Signal> {
T::resolutions()
.into_iter()
.filter(|(e, _, _)| e == entity)
.map(|(_, s, _)| s)
.collect()
}
pub fn ambiguous_entities<T: ContextDef>() -> Vec<T::Entity> {
let mut counts: HashMap<T::Entity, usize> = HashMap::new();
for (e, _, _) in T::resolutions() {
*counts.entry(e).or_default() += 1;
}
counts
.into_iter()
.filter(|(_, count)| *count > 1)
.map(|(e, _)| e)
.collect()
}
pub struct Deterministic<T: ContextDef> {
_marker: PhantomData<T>,
}
impl<T: ContextDef> Deterministic<T> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<T: ContextDef> Default for Deterministic<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: ContextDef> crate::logic::Axiom for Deterministic<T> {
fn description(&self) -> &str {
"context resolution is deterministic: each (entity, signal) has at most one resolution"
}
fn holds(&self) -> bool {
let resolutions = T::resolutions();
let mut seen: HashMap<(T::Entity, T::Signal), T::Resolution> = HashMap::new();
for (e, s, r) in resolutions {
if let Some(existing) = seen.get(&(e.clone(), s.clone())) {
if *existing != r {
return false;
}
} else {
seen.insert((e, s), r);
}
}
true
}
}
pub struct TrueAmbiguity<T: ContextDef> {
_marker: PhantomData<T>,
}
impl<T: ContextDef> TrueAmbiguity<T> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<T: ContextDef> Default for TrueAmbiguity<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: ContextDef> crate::logic::Axiom for TrueAmbiguity<T> {
fn description(&self) -> &str {
"every entity in the context map has at least two distinct resolutions"
}
fn holds(&self) -> bool {
let mut resolutions_per_entity: HashMap<T::Entity, Vec<T::Resolution>> = HashMap::new();
for (e, _, r) in T::resolutions() {
let rs = resolutions_per_entity.entry(e).or_default();
if !rs.contains(&r) {
rs.push(r);
}
}
resolutions_per_entity.values().all(|rs| rs.len() >= 2)
}
}