use geoit::algebra::mv::Mv;
use geoit::algebra::signature::Signature;
use geoit::builder::*;
use geoit::governance::Expr;
use geoit::scalar::{Rat, Scalar};
fn assert_circuit(gov: &NamedGovernance, class: &str, params: &[Scalar], label: &str) {
let mv = gov
.construct(class, params)
.unwrap_or_else(|e| panic!("[{}] construct failed: {}", label, e));
let geoit = gov
.govern(&mv, class)
.unwrap_or_else(|e| panic!("[{}] govern failed: {}", label, e));
assert!(
geoit.is_satisfied(),
"[{}] predicate failed at {:?}",
label,
geoit.predicate().failing_indices()
);
let extracted = geoit
.read_all()
.unwrap_or_else(|e| panic!("[{}] read_all failed: {}", label, e));
assert_eq!(extracted, params, "[{}] circuit didn't close", label);
}
fn assert_rejects(gov: &NamedGovernance, class: &str, mv: &Mv, label: &str) {
let result = gov.govern(mv, class);
assert!(
result.is_err() || !result.unwrap().is_satisfied(),
"[{}] should have been rejected",
label
);
}
fn vga3_gov() -> NamedGovernance {
let alg = Algebra::new(Signature::new(0, 0, 3).unwrap());
let class = GeomClassBuilder::new(&alg).grades(&[1]).build();
let 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)),
);
GovernanceBuilder::new(alg)
.class("Vector", class)
.construction("Vector", "Vector", 3, body)
.build()
}
#[test]
fn vga3_vector_integer() {
let gov = vga3_gov();
assert_circuit(
&gov,
"Vector",
&[Scalar::from(3), Scalar::from(4), Scalar::from(5)],
"VGA3 integer",
);
}
#[test]
fn vga3_vector_rational() {
let gov = vga3_gov();
assert_circuit(
&gov,
"Vector",
&[
Scalar::Rat(Rat::new(1, 2)),
Scalar::Rat(Rat::new(1, 3)),
Scalar::Rat(Rat::new(1, 7)),
],
"VGA3 rational",
);
}
#[test]
fn vga3_vector_negative() {
let gov = vga3_gov();
assert_circuit(
&gov,
"Vector",
&[Scalar::from(-1), Scalar::from(-2), Scalar::from(-3)],
"VGA3 negative",
);
}
#[test]
fn vga3_vector_zero() {
let gov = vga3_gov();
assert_circuit(
&gov,
"Vector",
&[Scalar::from(0), Scalar::from(0), Scalar::from(0)],
"VGA3 zero",
);
}
#[test]
fn vga3_rejects_bivector() {
let gov = vga3_gov();
let bv = Mv::from_rat_terms(&[(0b011, Rat::from(1))]);
assert_rejects(&gov, "Vector", &bv, "VGA3 bivector rejected");
}
fn pga2_gov() -> NamedGovernance {
let alg = Algebra::new(Signature::new(0, 1, 2).unwrap());
use geoit::governance::poly::Poly;
use geoit::governance::reading::VariableMap;
let gm = 0b10u64; let vm = VariableMap::for_grade_mask(alg.sig(), gm);
let mut weight = Poly::zero(vm.num_vars);
if let Some(&v2) = vm.mask_to_var.get(&0b010) {
let mut exp = vec![0u8; vm.num_vars];
exp[v2] = 2;
weight.add_term(exp, Rat::from(1));
}
if let Some(&v4) = vm.mask_to_var.get(&0b100) {
let mut exp = vec![0u8; vm.num_vars];
exp[v4] = 2;
weight.add_term(exp, Rat::from(1));
}
let class = GeomClassBuilder::new(&alg)
.grades(&[1])
.inequality(weight)
.build();
let body = Expr::Add(
Expr::add(
Expr::mul(Expr::param(0), Expr::gen(1)),
Expr::mul(Expr::param(1), Expr::gen(2)),
),
Expr::mul(Expr::param(2), Expr::gen(0)),
);
GovernanceBuilder::new(alg)
.class("Line", class)
.construction("Line", "Line", 3, body)
.build()
}
#[test]
fn pga2_line_circuit() {
let gov = pga2_gov();
assert_circuit(
&gov,
"Line",
&[Scalar::from(1), Scalar::from(0), Scalar::from(0)],
"PGA2 line",
);
assert_circuit(
&gov,
"Line",
&[Scalar::from(1), Scalar::from(1), Scalar::from(-3)],
"PGA2 line diagonal",
);
}
fn cga2_gov() -> NamedGovernance {
let mut alg = Algebra::new(Signature::new(1, 0, 3).unwrap());
let eo = Mv::from_rat_terms(&[(0b0001, Rat::new(1, 2)), (0b0010, Rat::new(1, 2))]);
let einf = Mv::from_rat_terms(&[(0b0001, Rat::from(-1)), (0b0010, Rat::from(1))]);
alg.add_derived("eo", eo);
alg.add_derived("einf", einf.clone());
let class = GeomClassBuilder::new(&alg)
.grades(&[1])
.null_constraint()
.normalization(&einf, 1)
.build();
let eucl = Expr::Add(
Expr::mul(Expr::param(0), Expr::gen(2)),
Expr::mul(Expr::param(1), Expr::gen(3)),
);
let r_sq = Expr::Add(
Expr::mul(Expr::param(0), Expr::param(0)),
Expr::mul(Expr::param(1), Expr::param(1)),
);
let neg_half_r2 = Expr::mul(
Box::new(Expr::Literal(Scalar::Rat(Rat::new(-1, 2)))),
Box::new(r_sq),
);
let conformal = Expr::Mul(neg_half_r2, Expr::dgen(1));
let body = Expr::Add(
Box::new(Expr::Add(Box::new(eucl), Box::new(conformal))),
Expr::dgen(0),
);
GovernanceBuilder::new(alg)
.class("Point", class)
.construction("Point", "Point", 2, body)
.build()
}
#[test]
fn cga2_point_origin() {
let gov = cga2_gov();
assert_circuit(
&gov,
"Point",
&[Scalar::from(0), Scalar::from(0)],
"CGA2 origin",
);
}
#[test]
fn cga2_point_integer() {
let gov = cga2_gov();
assert_circuit(
&gov,
"Point",
&[Scalar::from(3), Scalar::from(4)],
"CGA2 integer",
);
}
#[test]
fn cga2_point_rational() {
let gov = cga2_gov();
assert_circuit(
&gov,
"Point",
&[Scalar::Rat(Rat::new(1, 2)), Scalar::Rat(Rat::new(1, 3))],
"CGA2 rational",
);
}
#[test]
fn cga2_point_many() {
let gov = cga2_gov();
let cases: Vec<(i64, i64)> = vec![(0, 0), (1, 0), (0, 1), (3, 4), (-1, -1), (10, -7)];
for (x, y) in cases {
assert_circuit(
&gov,
"Point",
&[Scalar::from(x), Scalar::from(y)],
&format!("CGA2 ({},{})", x, y),
);
}
}
#[test]
fn cga2_point_null_verified() {
let gov = cga2_gov();
let mv = gov
.construct("Point", &[Scalar::from(3), Scalar::from(4)])
.unwrap();
let sig = *gov.sig();
let ns = geoit::algebra::ops::norm_squared(&mv, &sig);
assert!(ns.is_zero(), "CGA point should be null, got norm² = {}", ns);
}
fn sta_gov(sig: Signature) -> NamedGovernance {
let alg = Algebra::new(sig);
let class = GeomClassBuilder::new(&alg).grades(&[1]).build();
let body = Expr::Add(
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)),
),
Expr::mul(Expr::param(3), Expr::gen(3)),
);
GovernanceBuilder::new(alg)
.class("FourVector", class)
.construction("FourVector", "FourVector", 4, body)
.build()
}
#[test]
fn sta_west_coast() {
let gov = sta_gov(Signature::new(3, 0, 1).unwrap());
assert_circuit(
&gov,
"FourVector",
&[
Scalar::from(5),
Scalar::from(1),
Scalar::from(0),
Scalar::from(0),
],
"STA-WC",
);
}
#[test]
fn sta_east_coast() {
let gov = sta_gov(Signature::new(1, 0, 3).unwrap());
assert_circuit(
&gov,
"FourVector",
&[
Scalar::from(5),
Scalar::from(3),
Scalar::from(4),
Scalar::from(0),
],
"STA-EC",
);
}
fn qga3_gov() -> NamedGovernance {
let alg = Algebra::new(Signature::new(3, 0, 6).unwrap());
let class = GeomClassBuilder::new(&alg).grades(&[1]).build();
let mut body = Expr::mul(Expr::param(0), Expr::gen(0));
for k in 1..9u8 {
body = Expr::add(body, Expr::mul(Expr::param(k as usize), Expr::gen(k)));
}
GovernanceBuilder::new(alg)
.class("Vector", class)
.construction("Vector", "Vector", 9, *body)
.build()
}
#[test]
fn qga3_vector_circuit() {
let gov = qga3_gov();
let params: Vec<Scalar> = (1..=9).map(|i| Scalar::from(i as i64)).collect();
assert_circuit(&gov, "Vector", ¶ms, "QGA3 vector");
}
#[test]
fn qga3_sparse_circuit() {
let gov = qga3_gov();
let mut params: Vec<Scalar> = vec![Scalar::from(0); 9];
params[0] = Scalar::from(1);
params[8] = Scalar::from(-1);
assert_circuit(&gov, "Vector", ¶ms, "QGA3 sparse");
}