use crate::algebra::blade_new::grade;
use crate::algebra::mv::Mv;
use crate::algebra::signature::Signature;
use crate::governance::construction::{Construction, ConstructionError};
use crate::governance::field::ProbeSpec;
use crate::governance::geom_class::GeomClass;
use crate::governance::reading::VariableMap;
use crate::governance::rule::TransformRule;
use crate::scalar::{Rat, Scalar};
#[derive(Clone, Debug)]
pub struct Governance {
pub sig: Signature,
pub derived_gens: Vec<Mv>,
pub geom_classes: Vec<GeomClass>,
pub constructions: Vec<Construction>,
pub probe: Option<ProbeSpec>,
pub transform_rules: Vec<TransformRule>,
}
impl Governance {
pub fn from_parts(
sig: Signature,
derived_gens: Vec<Mv>,
geom_classes: Vec<GeomClass>,
constructions: Vec<Construction>,
probe: Option<ProbeSpec>,
) -> Self {
Governance {
sig,
derived_gens,
geom_classes,
constructions,
probe,
transform_rules: vec![],
}
}
pub fn sig(&self) -> &Signature {
&self.sig
}
pub fn derived_gens(&self) -> &[Mv] {
&self.derived_gens
}
pub fn num_classes(&self) -> usize {
self.geom_classes.len()
}
pub fn num_constructions(&self) -> usize {
self.constructions.len()
}
pub fn construct(
&self,
construction_index: usize,
params: &[Scalar],
) -> Result<Mv, ConstructionError> {
if construction_index >= self.constructions.len() {
return Err(ConstructionError::IndexOutOfRange {
index: construction_index,
len: self.constructions.len(),
});
}
self.constructions[construction_index].construct(
params,
&self.sig,
&self.derived_gens,
&self.constructions,
)
}
pub fn is_valid(&self, mv: &Mv, class_index: usize) -> bool {
let class = &self.geom_classes[class_index];
for (mask, coeff) in mv.blades() {
if !coeff.is_zero() && !class.grade_permitted(grade(mask)) {
return false;
}
}
let var_map = VariableMap::for_grade_mask(&self.sig, class.grade_mask);
let values: Vec<Rat> = var_map
.var_to_mask
.iter()
.map(|&mask| mv.coefficient(mask).try_as_rat().unwrap_or(Rat::ZERO))
.collect();
for eq in &class.equations {
if !eq.eval(&values).is_zero() {
return false;
}
}
for ineq in &class.inequalities {
if ineq.eval(&values).is_zero() {
return false;
}
}
true
}
}
impl Default for Governance {
fn default() -> Self {
Governance {
sig: Signature::new(0, 0, 0).unwrap(),
derived_gens: vec![],
geom_classes: vec![],
constructions: vec![],
probe: None,
transform_rules: vec![],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::governance::expr::Expr;
fn vga3_governance() -> Governance {
Governance {
sig: Signature::new(0, 0, 3).unwrap(),
derived_gens: vec![],
geom_classes: vec![GeomClass::grades_only(&[1])],
constructions: vec![Construction {
class_index: 0,
arity: 3,
body: Expr::Add(
Expr::add(
Expr::mul(Expr::param(0), Expr::gen(0)),
Expr::mul(Expr::param(1), Expr::gen(1)),
),
Expr::mul(Expr::param(2), Expr::gen(2)),
),
}],
probe: None,
transform_rules: vec![],
}
}
#[test]
fn governance_exists_without_mv() {
let gov = vga3_governance();
assert_eq!(gov.sig.n(), 3);
assert_eq!(gov.geom_classes.len(), 1);
assert_eq!(gov.constructions.len(), 1);
}
#[test]
fn construct_and_validate() {
let gov = vga3_governance();
let params = vec![Scalar::from(3i64), Scalar::from(4i64), Scalar::from(5i64)];
let mv = gov.construct(0, ¶ms).unwrap();
assert!(gov.is_valid(&mv, 0));
}
#[test]
fn invalid_mv() {
let gov = vga3_governance();
let bv = Mv::from_rat_terms(&[(0b011, crate::scalar::Rat::from(1))]);
assert!(!gov.is_valid(&bv, 0));
}
}