ComplexElement

Trait ComplexElement 

Source
pub trait ComplexElement:
    Clone
    + Hash
    + Eq
    + PartialOrd
    + Ord {
    // Required methods
    fn dimension(&self) -> usize;
    fn faces(&self) -> Vec<Self>;
    fn boundary_with_orientations(&self) -> Vec<(Self, i32)>;
    fn id(&self) -> Option<usize>;
    fn same_content(&self, other: &Self) -> bool;
    fn with_id(&self, new_id: usize) -> Self;
}
Expand description

Trait for elements that can be part of a topological complex.

This trait captures the essential behavior needed for elements (simplices, cubes, cells, etc.) to work with the generic Complex<T> structure. It abstracts over the common operations that any type of cell complex element must support.

§Mathematical Foundation

In algebraic topology, a complex is built from cells of various dimensions with specific face relations. This trait encapsulates the core properties that any cell type must have:

  1. Dimension: Each cell has an intrinsic dimension (0 for vertices, 1 for edges, etc.)
  2. Boundary Structure: Each cell has well-defined boundary cells (faces)
  3. Orientation: Boundary relationships include orientation information for chain complexes
  4. Identity: Cells can be uniquely identified when added to complexes
  5. Content Equality: Mathematical content can be compared regardless of ID assignment

§Design Philosophy

This trait is designed to be:

  • Generic: Works with simplices, cubes, and other cell types
  • Efficient: Supports ID-based operations for large complexes
  • Mathematically Correct: Preserves orientation and boundary relationships
  • Flexible: Allows different boundary operator conventions per element type

§Implementation Requirements

Types implementing this trait must:

  • Be cloneable, hashable, and orderable for use in collections
  • Compute their own faces and boundary operators correctly
  • Handle ID assignment and content comparison properly
  • Maintain mathematical consistency in their face relationships

§Examples

use harness_space::complexes::{ComplexElement, Simplex};

// Create a triangle (2-simplex)
let triangle = Simplex::new(2, vec![0, 1, 2]);

// Basic properties
assert_eq!(triangle.dimension(), 2);
assert_eq!(triangle.id(), None); // No ID until added to complex

// Compute faces (should be 3 edges)
let faces = triangle.faces();
assert_eq!(faces.len(), 3);
assert!(faces.iter().all(|face| face.dimension() == 1));

// Compute boundary with orientations
let boundary = triangle.boundary_with_orientations();
assert_eq!(boundary.len(), 3);
// Each face has orientation ±1
assert!(boundary.iter().all(|(_, orient)| orient.abs() == 1));

Required Methods§

Source

fn dimension(&self) -> usize

Returns the intrinsic dimension of this element.

The dimension determines the element’s place in the chain complex:

  • 0-dimensional: vertices/points
  • 1-dimensional: edges/curves
  • 2-dimensional: faces/surfaces
  • k-dimensional: k-cells
§Mathematical Note

For a k-dimensional element, its faces are (k-1)-dimensional, and it can be a face of (k+1)-dimensional elements. This creates the graded structure essential for homological computations.

§Examples
let vertex = Simplex::new(0, vec![42]);
assert_eq!(vertex.dimension(), 0);

let edge = Cube::edge(0, 1);
assert_eq!(edge.dimension(), 1);
Source

fn faces(&self) -> Vec<Self>

Returns all faces (boundary elements) of this element.

For a k-dimensional element, this returns all (k-1)-dimensional faces that form its boundary. This is the combinatorial boundary - it captures the face structure without orientation information.

§Mathematical Background

In topology, the boundary ∂σ of a cell σ consists of all the cells in its boundary. For example:

  • Triangle faces: the three edges forming its boundary
  • Tetrahedron faces: the four triangular faces
  • Square faces: the four edges forming its boundary
§Implementation Notes
  • Returned faces should have no ID assigned (will be assigned when added to complex)
  • The order may matter for orientation in ComplexElement::boundary_with_orientations
  • All faces must have dimension = self.dimension() - 1
  • 0-dimensional elements return empty vector (no (-1)-dimensional faces)
§Examples
// Triangle has 3 edge faces
let triangle = Simplex::new(2, vec![0, 1, 2]);
let faces = triangle.faces();
assert_eq!(faces.len(), 3);
assert!(faces.iter().all(|f| f.dimension() == 1));

// Vertex has no faces
let vertex = Simplex::new(0, vec![0]);
assert_eq!(vertex.faces().len(), 0);
Source

fn boundary_with_orientations(&self) -> Vec<(Self, i32)>

Returns the faces with their correct orientation coefficients for boundary computation.

This is the geometric boundary operator that includes orientation information necessary for chain complex computations. Each face comes with an integer coefficient (typically ±1) indicating its orientation in the boundary.

§Mathematical Foundation

In algebraic topology, the boundary operator ∂ₖ: Cₖ → Cₖ₋₁ is defined as:

∂ₖ(σ) = Σᵢ (-1)ⁱ τᵢ

where the τᵢ are the faces of σ with appropriate orientation signs. The key property is that ∂² = 0 (boundary of boundary is zero), which requires careful orientation handling.

§Orientation Conventions

Different element types may use different orientation conventions:

  • Simplicial: Alternating signs based on vertex position
  • Cubical: Signs based on coordinate directions
  • General CW: Depends on attaching maps
§Return Format

Returns Vec<(face, orientation)> where:

  • face: A (k-1)-dimensional face element (without ID)
  • orientation: Integer coefficient (usually ±1, could be 0)
§Examples
let triangle = Simplex::new(2, vec![0, 1, 2]);
let boundary = triangle.boundary_with_orientations();

// Triangle boundary: [v₁,v₂] - [v₀,v₂] + [v₀,v₁]
assert_eq!(boundary.len(), 3);
assert_eq!(boundary[0].1, 1); // +[v₁,v₂]
assert_eq!(boundary[1].1, -1); // -[v₀,v₂]
assert_eq!(boundary[2].1, 1); // +[v₀,v₁]
Source

fn id(&self) -> Option<usize>

Returns the ID if this element has been assigned to a complex, None otherwise.

IDs are automatically assigned when elements are added to a Complex via Complex::join_element. They serve as unique identifiers for efficient storage and lookup operations.

§ID Assignment Lifecycle
  1. Created: Element starts with id() = None
  2. Added: Complex assigns unique ID via ComplexElement::with_id
  3. Stored: Element with ID is stored in complex’s HashMap
  4. Referenced: ID used for lattice operations and lookups
§Examples
let simplex = Simplex::new(1, vec![0, 1]);
assert_eq!(simplex.id(), None);

let mut complex = Complex::new();
let added = complex.join_element(simplex);
assert!(added.id().is_some());
Source

fn same_content(&self, other: &Self) -> bool

Checks if this element has the same mathematical content as another.

This comparison ignores ID assignment and focuses purely on the mathematical structure of the elements. It’s used for deduplication when adding elements to complexes.

§Mathematical Equality

Two elements are considered to have the same content if they represent the same mathematical object, regardless of:

  • ID assignment (internal bookkeeping)
  • Order of discovery (when added to complex)
  • Memory location or other implementation details
§Usage in Complexes

When Complex::join_element is called, it first checks if an element with the same content already exists using this method. If found, it returns the existing element rather than creating a duplicate.

§Examples
let simplex1 = Simplex::new(1, vec![0, 1]);
let simplex2 = Simplex::new(1, vec![0, 1]);
let simplex3 = simplex1.clone().with_id(42);

assert!(simplex1.same_content(&simplex2)); // Same mathematical content
assert!(simplex1.same_content(&simplex3)); // ID differences ignored

let different = Simplex::new(1, vec![0, 2]);
assert!(!simplex1.same_content(&different)); // Different content
Source

fn with_id(&self, new_id: usize) -> Self

Creates a new element with the same content but a specific ID.

This is used internally by Complex to assign IDs when adding elements. The returned element should be identical in all mathematical properties but have the specified ID assigned.

§Implementation Requirements

The returned element must satisfy:

  • result.same_content(self) == true
  • result.id() == Some(new_id)
  • All other properties unchanged (dimension, faces, etc.)
§Usage

This method is primarily used internally by the complex management system. Users typically don’t need to call it directly.

§Examples
let original = Simplex::new(1, vec![0, 1]);
assert_eq!(original.id(), None);

let with_id = original.with_id(42);
assert_eq!(with_id.id(), Some(42));
assert!(original.same_content(&with_id));
assert_eq!(original.dimension(), with_id.dimension());

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§