Skip to main content

clifford_codegen/discovery/
entity.rs

1//! Discovered entity representation.
2
3/// Represents a discovered geometric entity.
4///
5/// An entity is a valid grade combination with associated metadata.
6/// Valid entities must satisfy two constraints:
7///
8/// 1. **Geometric Product Constraint**: `u * ũ = scalar`
9/// 2. **Antiproduct Constraint**: `u ⊟ ũ̃ = antiscalar`
10///
11/// Each constraint may require a field constraint expression that must equal zero.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct DiscoveredEntity {
14    /// Suggested name for this entity (e.g., "Entity_0_2").
15    pub name: String,
16
17    /// The grades present in this entity.
18    pub grades: Vec<usize>,
19
20    /// Field constraint for the geometric product constraint (`u * ũ = scalar`).
21    ///
22    /// If `None`, the entity automatically satisfies the geometric constraint.
23    /// If `Some(expr)`, the expression must equal zero for the constraint to hold.
24    /// Example: "e01*e23 + e02*e31 + e03*e12 = 0" for PGA bivectors.
25    pub geometric_constraint: Option<String>,
26
27    /// Field constraint for the antiproduct constraint (`u ⊟ ũ̃ = antiscalar`).
28    ///
29    /// If `None`, the entity automatically satisfies the antiproduct constraint.
30    /// If `Some(expr)`, the expression must equal zero for the constraint to hold.
31    pub antiproduct_constraint: Option<String>,
32}
33
34impl DiscoveredEntity {
35    /// Creates a new discovered entity with minimal information.
36    pub fn new(name: impl Into<String>, grades: Vec<usize>) -> Self {
37        Self {
38            name: name.into(),
39            grades,
40            geometric_constraint: None,
41            antiproduct_constraint: None,
42        }
43    }
44
45    /// Sets the geometric field constraint expression.
46    pub fn with_geometric_constraint(mut self, constraint: impl Into<String>) -> Self {
47        self.geometric_constraint = Some(constraint.into());
48        self
49    }
50
51    /// Sets the antiproduct field constraint expression.
52    pub fn with_antiproduct_constraint(mut self, constraint: impl Into<String>) -> Self {
53        self.antiproduct_constraint = Some(constraint.into());
54        self
55    }
56
57    /// Returns the total number of constraints this entity has.
58    pub fn constraint_count(&self) -> usize {
59        let mut count = 0;
60        if self.geometric_constraint.is_some() {
61            count += 1;
62        }
63        if self.antiproduct_constraint.is_some() {
64            count += 1;
65        }
66        count
67    }
68
69    /// Returns true if this entity has any field constraints.
70    pub fn has_constraints(&self) -> bool {
71        self.geometric_constraint.is_some() || self.antiproduct_constraint.is_some()
72    }
73}