Exemple #1
0
 def test_by_label( self ):
     s0, s1 = Mock( spec=SymmetryOperation ), Mock( spec=SymmetryOperation )
     s0.label = 'A'
     s1.label = 'B'
     sg = SymmetryGroup( symmetry_operations=[ s0, s1 ] )
     self.assertEqual( sg.by_label( 'A' ), s0 )
     self.assertEqual( sg.by_label( 'B' ), s1 )
 def test_by_label(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     s0.label = 'A'
     s1.label = 'B'
     sg = SymmetryGroup(symmetry_operations=[s0, s1])
     self.assertEqual(sg.by_label('A'), s0)
     self.assertEqual(sg.by_label('B'), s1)
Exemple #3
0
 def test_save_symmetry_operation_vectors_to( self ):
     s0, s1 = Mock( spec=SymmetryOperation ), Mock( spec=SymmetryOperation )
     s0.as_vector.return_value = [ 1, 2 ]
     s1.as_vector.return_value = [ 2, 1 ]
     sg = SymmetryGroup( symmetry_operations=[ s0, s1 ] )
     with patch( 'numpy.savetxt' ) as mock_savetxt:
         sg.save_symmetry_operation_vectors_to( 'filename' ) 
         self.assertEqual( mock_savetxt.call_args[0][0], 'filename' )
         np.testing.assert_array_equal( mock_savetxt.call_args[0][1], np.array( [ [ 1, 2 ], [ 2, 1 ] ] ) )
 def test_save_symmetry_operation_vectors_to(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     s0.as_vector.return_value = [1, 2]
     s1.as_vector.return_value = [2, 1]
     sg = SymmetryGroup(symmetry_operations=[s0, s1])
     with patch('numpy.savetxt') as mock_savetxt:
         sg.save_symmetry_operation_vectors_to('filename')
         self.assertEqual(mock_savetxt.call_args[0][0], 'filename')
         np.testing.assert_array_equal(mock_savetxt.call_args[0][1],
                                       np.array([[1, 2], [2, 1]]))
Exemple #5
0
 def test_read_from_file( self ):
     s0, s1 = Mock( spec=SymmetryOperation ), Mock( spec=SymmetryOperation )
     with patch( 'numpy.loadtxt' ) as mock_np_loadtxt:
         mock_np_loadtxt.return_value = np.array( [ [ 1, 2 ], [ 2, 1 ] ] )
         with patch( 'bsym.symmetry_operation.SymmetryOperation.from_vector' ) as mock_from_vector:
             mock_from_vector.side_effect = [ s0, s1 ]
             sg = SymmetryGroup.read_from_file( 'mock_filename' )
             self.assertEqual( sg.symmetry_operations[0], s0 )
             self.assertEqual( sg.symmetry_operations[1], s1 )
             self.assertEqual( mock_from_vector.call_args_list[0], call( [ 1, 2 ] ) )
             self.assertEqual( mock_from_vector.call_args_list[1], call( [ 2, 1 ] ) )
Exemple #6
0
    def __init__( self, objects, symmetry_group=None ):
        """
        Create a :any:`ConfigurationSpace` object.
  
        Args:
            objects (list): The set of objects that define the vector space of this configuration space.
            symmetry_group (:any:`SymmetryGroup`): The set of symmetry operations describing the symmetries of this configuration space.

        Returns:
            None
        """
        # Check that all properties have compatible dimensions
        self.dim = len( objects )
        self.objects = objects
        if symmetry_group:
            for so in symmetry_group.symmetry_operations:
                if so.matrix.shape[0] != self.dim:
                    raise ValueError
            self.symmetry_group = symmetry_group
        else:
            self.symmetry_group = SymmetryGroup( symmetry_operations=[ SymmetryOperation( np.identity( self.dim, dtype=int ), label='E' ) ] )
Exemple #7
0
 def test_read_from_file_with_labels( self ):
     s0, s1 = Mock( spec=SymmetryOperation ), Mock( spec=SymmetryOperation )
     with patch( 'numpy.genfromtxt' ) as mock_np_genfromtxt:
         mock_np_genfromtxt.return_value = np.array( [ [ 'E', '1', '2' ], [ 'C2', '2', '1' ] ] )
         with patch( 'bsym.symmetry_operation.SymmetryOperation.from_vector' ) as mock_from_vector:
             mock_from_vector.side_effect = [ s0, s1 ]
             sg = SymmetryGroup.read_from_file_with_labels( 'mock_filename' )
             self.assertEqual( sg.symmetry_operations[0], s0 )
             self.assertEqual( sg.symmetry_operations[1], s1 )
             self.assertEqual( mock_from_vector.call_args_list[0], call( [ 1, 2 ] ) )
             self.assertEqual( mock_from_vector.call_args_list[1], call( [ 2, 1 ] ) )
             self.assertEqual( s0.set_label.call_args, call( 'E' ) )
             self.assertEqual( s1.set_label.call_args, call( 'C2' ) )
 def test_read_from_file(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     with patch('numpy.loadtxt') as mock_np_loadtxt:
         mock_np_loadtxt.return_value = np.array([[1, 2], [2, 1]])
         with patch('bsym.symmetry_operation.SymmetryOperation.from_vector'
                    ) as mock_from_vector:
             mock_from_vector.side_effect = [s0, s1]
             sg = SymmetryGroup.read_from_file('mock_filename')
             self.assertEqual(sg.symmetry_operations[0], s0)
             self.assertEqual(sg.symmetry_operations[1], s1)
             self.assertEqual(mock_from_vector.call_args_list[0],
                              call([1, 2]))
             self.assertEqual(mock_from_vector.call_args_list[1],
                              call([2, 1]))
 def test_read_from_file_with_labels(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     with patch('numpy.genfromtxt') as mock_np_genfromtxt:
         mock_np_genfromtxt.return_value = np.array([['E', '1', '2'],
                                                     ['C2', '2', '1']])
         with patch('bsym.symmetry_operation.SymmetryOperation.from_vector'
                    ) as mock_from_vector:
             mock_from_vector.side_effect = [s0, s1]
             sg = SymmetryGroup.read_from_file_with_labels('mock_filename')
             self.assertEqual(sg.symmetry_operations[0], s0)
             self.assertEqual(sg.symmetry_operations[1], s1)
             self.assertEqual(mock_from_vector.call_args_list[0],
                              call([1, 2]))
             self.assertEqual(mock_from_vector.call_args_list[1],
                              call([2, 1]))
             self.assertEqual(s0.set_label.call_args, call('E'))
             self.assertEqual(s1.set_label.call_args, call('C2'))
Exemple #10
0
class ConfigurationSpace:
    def __init__(self, objects, symmetry_group=None):
        """
        Create a :any:`ConfigurationSpace` object.
  
        Args:
            objects (list): The set of objects that define the vector space of this configuration space.
            symmetry_group (:any:`SymmetryGroup`): The set of symmetry operations describing the symmetries of this configuration space.

        Returns:
            None
        """
        # Check that all properties have compatible dimensions
        dim = len(objects)
        self.objects = objects
        if symmetry_group:
            for so in symmetry_group.symmetry_operations:
                if so.matrix.shape[0] != dim:
                    raise ValueError
            self.symmetry_group = symmetry_group
        else:
            self.symmetry_group = SymmetryGroup(symmetry_operations=[
                SymmetryOperation(np.identity(dim, dtype=int), label='E')
            ])

    def __repr__(self):
        to_return = "ConfigurationSpace\n"
        to_return += self.objects.__repr__() + "\n"
        to_return += "\n".join(self.symmetry_group.__repr__().split("\n")[1:])
        return to_return

    def unique_configurations(self, site_distribution, verbose=False):
        """
        Find the symmetry inequivalent configurations for a given population of objects.

        Args:
            site_distribution (dict): A dictionary that defines the number of each object 
                                      to be arranged in this system.

                                      e.g. for a system with four sites, with two occupied (denoted `1`)
                                      and two unoccupied (denoted `0`)::

                                          { 1 : 2, 2 : 1 }
            verbose (opt:default=False): Print verbose output.

        Returns:
            unique_configurations (list): A list of :any:`Configuration` objects, for each symmetry 
                                          inequivalent configuration. 
        """
        if verbose:
            print('total number of sites: ' +
                  str(sum(site_distribution.values())))
            print('using {:d} symmetry operations: '.format(
                len(self.symmetry_group.symmetry_operations)))
        permutations = []
        working = True
        seen = set()
        unique_configurations = []
        s = flatten_list([[key] * site_distribution[key]
                          for key in site_distribution])
        for new_permutation in unique_permutations(s):
            if permutation_as_config_number(new_permutation) not in seen:
                config = Configuration.from_tuple(new_permutation)
                numeric_equivalents = set(
                    config.numeric_equivalents(
                        self.symmetry_group.symmetry_operations))
                config.count = len(numeric_equivalents)
                [seen.add(i) for i in numeric_equivalents]
                unique_configurations.append(config)
                if verbose:
                    print("found {:d}, screened {:d}".format(
                        len(unique_configurations), len(seen)))
        if verbose:
            print('unique configurations: ' + str(len(unique_configurations)))
        return (unique_configurations)
Exemple #11
0
class ConfigurationSpace:

    def __init__( self, objects, symmetry_group=None ):
        """
        Create a :any:`ConfigurationSpace` object.
  
        Args:
            objects (list): The set of objects that define the vector space of this configuration space.
            symmetry_group (:any:`SymmetryGroup`): The set of symmetry operations describing the symmetries of this configuration space.

        Returns:
            None
        """
        # Check that all properties have compatible dimensions
        self.dim = len( objects )
        self.objects = objects
        if symmetry_group:
            for so in symmetry_group.symmetry_operations:
                if so.matrix.shape[0] != self.dim:
                    raise ValueError
            self.symmetry_group = symmetry_group
        else:
            self.symmetry_group = SymmetryGroup( symmetry_operations=[ SymmetryOperation( np.identity( self.dim, dtype=int ), label='E' ) ] )

    def __repr__( self ):
        to_return = "ConfigurationSpace\n"
        to_return += self.objects.__repr__() + "\n"
        to_return += "\n".join( self.symmetry_group.__repr__().split("\n")[1:] )
        return to_return

    def enumerate_configurations( self, generator, verbose=False ):
        """
        Find all symmetry inequivalent configurations within the set produced by
        `generator`.

        Args:
            generator (:obj:`generator`): Generator object, that yields the configurations
                to search through.
            verbose (opt:default=False): Print verbose output.
   
        Returns:
            unique_configurations (list): A list of :any:`Configuration` objects, for each symmetry
                                          inequivalent configuration. 
        """
        working = True
        seen = set()
        unique_configurations = []
        using_tqdm = hasattr( generator, 'postfix' )
        for new_permutation in generator:
            if permutation_as_config_number( new_permutation ) not in seen:
                config = Configuration.from_tuple( new_permutation )
                numeric_equivalents = set( config.numeric_equivalents( self.symmetry_group.symmetry_operations ) )
                config.count = len( numeric_equivalents )
                [ seen.add( i ) for i in numeric_equivalents ]
                unique_configurations.append( config )
                if using_tqdm:
                    generator.set_postfix( found=len(unique_configurations) )
        if verbose:
            print( 'unique configurations: {} / {}'.format( len( unique_configurations ), len( seen ) ) )
        return( unique_configurations )

    def unique_configurations( self, site_distribution, verbose=False, show_progress=False ):
        """
        Find the symmetry inequivalent configurations for a given population of objects.

        Args:
            site_distribution (dict): A dictionary that defines the number of each object 
                                      to be arranged in this system.

                                      e.g. for a system with four sites, with two occupied (denoted `1`)
                                      and two unoccupied (denoted `0`)::

                                          { 1: 2, 0: 2 }
            verbose (opt:default=False): Print verbose output.
            show_progress (opt:default=False): Show a progress bar.
                                      Setting to `True` gives a simple progress bar.
                                      Setting to `"notebook"` gives a Jupyter notebook compatible progress bar.

        Returns:
            unique_configurations (list): A list of :any:`Configuration` objects, for each symmetry 
                                          inequivalent configuration. 
        """
        s = flatten_list( [ [ key ] * site_distribution[ key ] for key in site_distribution ] )
        total_permutations = number_of_unique_permutations( s )
        if verbose:
            print( 'total number of sites: ' + str( sum( site_distribution.values() ) ) )
            print( 'using {:d} symmetry operations.'.format( len( self.symmetry_group.symmetry_operations ) ) )
            print( 'evaluating {:d} unique permutations.'.format( total_permutations ) )
        generator = unique_permutations( s )
        if show_progress:
            if show_progress=='notebook':
                generator = tqdm_notebook( generator, total=total_permutations, unit=' permutations' )
            else:
                generator = tqdm( generator, total=total_permutations, unit=' permutations' )
        return self.enumerate_configurations( generator, verbose=verbose )

    def unique_colourings( self, colours, verbose=False ):
        """
        Find the symmetry inequivalent colourings for a given number of 'colours'.

        Args:
            colours (list): A list of each object that may be arranged zero or more times in this system.
            verbose (opt:default=False): Print verbose output.

        Returns:
            unique_colours (list): A list of :any:`Configuration` objects, for each symmetry
                                   inequivalent colouring.
        """
        generator = colourings_generator( colours, self.dim )
        return self.enumerate_configurations( generator, verbose=verbose )
Exemple #12
0
 def test_append( self ):
     s0, s1 = Mock( spec=SymmetryOperation ), Mock( spec=SymmetryOperation )
     sg = SymmetryGroup( symmetry_operations=[ s0, s1 ] )
     s2 = Mock( spec=SymmetryOperation)
     sg.append( s2 )
     self.assertEqual( sg.symmetry_operations, [ s0, s1, s2 ] )
 def test_labels(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     s0.label = 'A'
     s1.label = 'B'
     sg = SymmetryGroup(symmetry_operations=[s0, s1])
     self.assertEqual(sg.labels, ['A', 'B'])
 def test_symmetry_group_is_initialised(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     sg = SymmetryGroup(symmetry_operations=[s0, s1])
     self.assertEqual(sg.symmetry_operations[0], s0)
     self.assertEqual(sg.symmetry_operations[1], s1)
 def test_append(self):
     s0, s1 = Mock(spec=SymmetryOperation), Mock(spec=SymmetryOperation)
     sg = SymmetryGroup(symmetry_operations=[s0, s1])
     s2 = Mock(spec=SymmetryOperation)
     sg.append(s2)
     self.assertEqual(sg.symmetry_operations, [s0, s1, s2])