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:
A vector space - n positions in a vector (indexed 0, 1, 2, …, n-1)
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:
then [1, 1, 0] represents:
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:
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
0and1(e.g., vacant/occupied, or species A/species B)Ternary system: labels
0,1, and2(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:
Define the abstract configuration space - vector dimension and symmetry operations
Enumerate configurations - find unique arrangements using vector-based algorithms
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.