Configuration Spaces

What is a Configuration Space?

A configuration space is an abstract vector space that represents possible arrangements of distinguishable objects. A configuration space consists of:

  1. A vector space - n positions in a vector (indexed 0, 1, 2, …, n-1)

  2. Object labels - integers representing different types or species

This abstract framework can represent many different systems: atoms distributed across crystallographic sites, molecular conformations, states at discrete time steps, or any other system where discrete objects can be arranged in different ways.

A Simple Example

Consider a 3-dimensional vector space. We can represent arrangements of two types of objects (labelled 0 and 1) as vectors like [1, 1, 0].

If we interpret this vector as three sites in a triangle:

Triangular configuration space

then [1, 1, 0] represents:

Triangular configuration example

where positions 0 and 1 have object type 1 (shown in black), and position 2 has object type 0 (shown in white).

Different arrangements like [0, 1, 1] or [1, 0, 1] represent different configurations within the same configuration space.

Configurations vs Configuration Spaces

  • Configuration Space: The vector space itself (e.g., “3-dimensional space”)

  • Configuration: A specific assignment of labels (e.g., [1, 1, 0])

Mathematical Representation

Configuration Vectors

Each configuration is represented as a vector of integers. For a configuration space with n positions, a configuration is an n-element vector:

\[\begin{split}\mathbf{v} = \begin{pmatrix}v_0\\v_1\\v_2\\\vdots\\v_{n-1}\end{pmatrix}\end{split}\]

where each \(v_i\) is a non-negative integer representing the type of object at position \(i\).

Object Labels

Object labels are arbitrary integers. Objects with the same label are considered indistinguishable. For example:

  • Binary system: labels 0 and 1 (e.g., vacant/occupied, or species A/species B)

  • Ternary system: labels 0, 1, and 2 (e.g., three different atomic species)

  • Multi-species: any number of distinct integer labels

The specific integers used as labels are arbitrary - what matters is which positions have the same or different labels.

Examples

For a 4-dimensional configuration space:

  • [0, 0, 1, 1] - positions 0 and 1 have type 0, positions 2 and 3 have type 1

  • [0, 1, 0, 1] - positions 0 and 2 have type 0, positions 1 and 3 have type 1

  • [2, 2, 1, 0] - position 0 has type 2, position 1 has type 2, position 2 has type 1, position 3 has type 0

  • [1, 1, 1, 1] - all positions have type 1

Each vector represents a distinct configuration. Whether two configurations like [0, 0, 1, 1] and [0, 1, 0, 1] are equivalent depends on the symmetry operations defined for the configuration space (discussed in the next section).

The Configuration and ConfigurationSpace Classes

The Configuration Class

In bsym, individual configurations are represented by Configuration objects. A Configuration stores:

  • A vector: The integer array representing the configuration

  • Metadata: Optional attributes like degeneracy counts

Creating a configuration:

from bsym import Configuration

config = Configuration([1, 1, 0, 0])

Numeric Representation

Each configuration has a numeric representation accessed via the as_number property. This provides a unique integer identifier for the configuration:

config = Configuration([1, 2, 0])
print(config.as_number)  # Output: 120

This numeric representation is primarily used internally for efficient comparison and hashing of configurations during symmetry analysis.

The ConfigurationSpace Class

A ConfigurationSpace object combines:

  • Objects: A list defining the dimensionality of the space

  • Symmetry group: Optional symmetry operations (defaults to identity only)

The objects list defines the vector space dimension:

from bsym import ConfigurationSpace

# Create a 4-dimensional configuration space
config_space = ConfigurationSpace(objects=[1, 2, 3, 4])

The integers in the objects list serve as labels for the vector positions - they don’t represent the configuration itself. They’re often just sequential integers [1, 2, 3, ..., n], but can be any distinct values.

Configuration Space Without Symmetry

A ConfigurationSpace can be created without specifying symmetry operations. In this case, it contains only the identity operation, meaning no configurations are considered equivalent:

config_space = ConfigurationSpace(objects=[1, 2, 3])
# Implicitly has only the identity symmetry operation

This is useful when you want to use the configuration space framework but don’t need to identify symmetry-equivalent configurations.

Why Use Abstract Representation?

Separation of Concerns

The abstract vector representation separates the mathematical logic of symmetry analysis from the physical details of specific systems. This means:

  • Symmetry algorithms work at the vector level, independent of coordinates or structures

  • Physical interpretation is added as a separate layer when needed

  • The same code handles crystals, molecules, or any other symmetric system

Computational Efficiency

Working with integer vectors is computationally efficient:

  • Integer comparisons are fast

  • Vectors can be hashed and stored in sets/dictionaries

  • No floating-point arithmetic or coordinate transformations needed during enumeration

  • Symmetry operations are simple permutations of integer indices - just rearranging vector elements rather than matrix-vector multiplication with floating-point coordinates

Generality

The abstract approach makes bsym applicable to any problem involving symmetric arrangements of discrete objects. You’re not limited to crystallographic applications - the same framework handles:

  • Disorder in crystal structures

  • Molecular conformations

  • Combinatorial problems with symmetry constraints

  • Abstract group theory problems

From Abstract to Physical

When working with real systems, the workflow is:

  1. Define the abstract configuration space - vector dimension and symmetry operations

  2. Enumerate configurations - find unique arrangements using vector-based algorithms

  3. Map to physical structures - interpret abstract configurations as coordinates, structures, etc.

This separation allows the expensive symmetry analysis to happen at the abstract level, then efficiently generate corresponding physical structures only for the unique configurations.

Connecting to Real Structures

The CoordinateConfigSpace Class

For systems where vector positions correspond to physical coordinates, bsym provides CoordinateConfigSpace, which extends ConfigurationSpace with coordinate information:

from bsym import CoordinateConfigSpace
import numpy as np

# Define coordinates for each position
coordinates = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]])

# Create configuration space with coordinates
coord_space = CoordinateConfigSpace(coordinates, symmetry_group=my_symmetry_group)

The CoordinateConfigSpace maintains the abstract vector representation internally while also storing the associated coordinates. This allows symmetry analysis to happen at the abstract level, with results mapped back to coordinates when needed.

The Pymatgen Interface

For crystallographic applications, bsym provides an interface to work with pymatgen Structure objects. This handles:

  • Extracting symmetry operations from crystal structures

  • Converting between abstract configurations and atomic structures

  • Generating symmetry-inequivalent crystal structures from substitution patterns

The pymatgen interface is covered in detail in the User Guide. The key point is that it operates as a wrapper around the abstract ConfigurationSpace machinery - symmetry analysis happens at the vector level, then results are converted to Structure objects.