use crate::algebra::mv::Mv;
use crate::governance::composition::Embedding;
use crate::governance::geoit::Geoit;
use crate::governance::governance::Governance;
use crate::governance::phase;
use crate::governance::predicate::Predicate;
use crate::governance::profile::GeneratorProfile;
use crate::governance::reading::ReadingRules;
use crate::governance::rule::ProofTerm;
use crate::governance::GovernanceError;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct GovernedMorphism {
pub name: String,
pub embedding: Embedding,
pub source_gov_index: usize,
pub target_gov_index: usize,
pub class_map: Vec<Option<usize>>,
}
impl GovernedMorphism {
pub fn embed_mv(&self, mv: &Mv) -> Mv {
self.embedding.embed_mv(mv)
}
}
#[derive(Clone, Debug, Default)]
pub struct GovernanceCategory {
pub governances: Vec<Arc<Governance>>,
pub names: Vec<String>,
pub morphisms: Vec<GovernedMorphism>,
}
impl GovernanceCategory {
pub fn new() -> Self {
Self::default()
}
pub fn add_governance(&mut self, name: impl Into<String>, gov: Governance) -> usize {
let idx = self.governances.len();
self.governances.push(Arc::new(gov));
self.names.push(name.into());
idx
}
pub fn add_morphism(&mut self, morphism: GovernedMorphism) {
self.morphisms.push(morphism);
}
pub fn governance_by_name(&self, name: &str) -> Option<(usize, &Arc<Governance>)> {
self.names
.iter()
.enumerate()
.find(|(_, n)| n.as_str() == name)
.map(|(i, _)| (i, &self.governances[i]))
}
pub fn find_morphism(&self, source: usize, target: usize) -> Option<&GovernedMorphism> {
self.morphisms
.iter()
.find(|m| m.source_gov_index == source && m.target_gov_index == target)
}
pub fn morphism_by_name(&self, name: &str) -> Option<&GovernedMorphism> {
self.morphisms.iter().find(|m| m.name == name)
}
pub fn embed_geoit(
&self,
geoit: &Geoit,
morphism_name: &str,
) -> Result<Geoit, GovernanceError> {
let morph = self
.morphism_by_name(morphism_name)
.ok_or(GovernanceError::ClassOutOfRange { index: 0, len: 0 })?;
let target_gov = &self.governances[morph.target_gov_index];
let target_mv = morph.embed_mv(geoit.mv());
let source_class = geoit.predicate().class_index;
let target_class = morph.class_map.get(source_class).and_then(|c| *c).ok_or(
GovernanceError::ClassOutOfRange {
index: source_class,
len: morph.class_map.len(),
},
)?;
let ph = phase::compute_phase(&target_mv, &target_gov.sig);
let prof = GeneratorProfile::compute(&target_mv, &target_gov.sig);
let class = &target_gov.geom_classes[target_class];
let readings = if let Some(constr) = target_gov
.constructions
.iter()
.find(|c| c.class_index == target_class)
{
ReadingRules::derive_from_probing(constr, &target_gov.sig, &target_gov.derived_gens)
.unwrap_or_else(|_| ReadingRules::derive_from_grade_mask(class, 0, &target_gov.sig))
} else {
ReadingRules::derive_from_grade_mask(class, 0, &target_gov.sig)
};
let pred = Predicate::new(
target_class,
&[],
&[],
vec![true; class.equations.len()],
vec![true; class.inequalities.len()],
false,
);
Ok(Geoit {
mv: target_mv,
governance: Arc::clone(target_gov),
predicate: pred,
phase: ph,
readings,
profile: prof,
proof: ProofTerm::Derived {
rule_name: format!("embed({})", morph.name),
input_proofs: vec![Box::new(geoit.proof.clone())],
},
})
}
pub fn compose_morphisms(&self, f_name: &str, g_name: &str) -> Option<GovernedMorphism> {
let f = self.morphism_by_name(f_name)?;
let g = self.morphism_by_name(g_name)?;
if f.target_gov_index != g.source_gov_index {
return None;
}
let source_sig = &f.embedding.source_sig;
let target_sig = &g.embedding.target_sig;
let composed_map: Vec<u8> = f
.embedding
.generator_map
.iter()
.map(|&mid_gen| g.embedding.generator_map[mid_gen as usize])
.collect();
let embedding = Embedding::new(*source_sig, *target_sig, composed_map).ok()?;
let class_map: Vec<Option<usize>> = f
.class_map
.iter()
.map(|fc| fc.and_then(|mid_class| g.class_map.get(mid_class).and_then(|gc| *gc)))
.collect();
Some(GovernedMorphism {
name: format!("{}∘{}", g_name, f_name),
embedding,
source_gov_index: f.source_gov_index,
target_gov_index: g.target_gov_index,
class_map,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_category() {
let cat = GovernanceCategory::new();
assert_eq!(cat.governances.len(), 0);
assert_eq!(cat.morphisms.len(), 0);
}
#[test]
fn add_governance() {
let mut cat = GovernanceCategory::new();
let gov = Governance::default();
let idx = cat.add_governance("test", gov);
assert_eq!(idx, 0);
assert!(cat.governance_by_name("test").is_some());
assert!(cat.governance_by_name("missing").is_none());
}
}