TiledArray  0.7.0
permutation_group.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2015 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Edward F Valeev, Justus Calvin
19  * Department of Chemistry, Virginia Tech
20  *
21  * permutation_group.h
22  * May 13, 2015
23  *
24  */
25 
26 #ifndef TILEDARRAY_SYMM_PERMUTATION_GROUP_H__INCLUDED
27 #define TILEDARRAY_SYMM_PERMUTATION_GROUP_H__INCLUDED
28 
29 #include <numeric>
30 #include <algorithm>
31 #include <cassert>
32 
34 
35 namespace TiledArray {
36 
37  namespace symmetry {
38 
44 
49  public:
52 
53  protected:
54 
56  std::vector<Permutation> generators_;
58  std::vector<Permutation> elements_;
59 
60  public:
61 
62  // Compiler generated functions
63  PermutationGroup(const PermutationGroup&) = default;
65  PermutationGroup& operator=(const PermutationGroup&) = default;
67 
69 
75  PermutationGroup(std::vector<Permutation> generators) :
76  generators_(std::move(generators))
77  {
79  }
80 
82 
86  unsigned int order() const { return elements_.size(); }
87 
89 
91  static Permutation identity() { return Permutation(); }
92 
94 
98  const Permutation& operator[](unsigned int i) const {
99  TA_ASSERT(i < elements_.size());
100  return elements_[i];
101  }
102 
104 
107  const std::vector<Permutation>& elements() const { return elements_; }
108 
110 
113  const std::vector<Permutation>& generators() const { return generators_; }
114 
116 
120 
122 
124  std::vector<Permutation>::const_iterator begin() const {
125  return elements_.begin();
126  }
127 
129 
131  std::vector<Permutation>::const_iterator cbegin() const {
132  return elements_.cbegin();
133  }
134 
136 
138  std::vector<Permutation>::const_iterator end() const {
139  return elements_.end();
140  }
141 
143 
145  std::vector<Permutation>::const_iterator cend() const {
146  return elements_.cend();
147  }
148 
150 
152 
155  template <typename Set>
156  Set domain() const {
157  Set result;
158  // sufficient to loop over generators
159  for(const auto& e: generators_) {
160  const auto e_domain = e.domain<Set>();
161  result.insert(e_domain.begin(), e_domain.end());
162  }
163  return result;
164  }
165 
166 
167  protected:
168 
169  PermutationGroup() {} // makes uninitialized group, all initialization is left to the derived class
170 
174  static void init(std::vector<Permutation>& generators,
175  std::vector<Permutation>& elements) {
176 
177  sort(generators.begin(), generators.end());
178  auto unique_last = std::unique(generators.begin(), generators.end());
179  generators.erase(unique_last, generators.end());
180  { // eliminate identity from the generator list
181  auto I_iter = std::find(generators.begin(), generators.end(), Permutation());
182  if (I_iter != generators.end())
183  generators.erase(I_iter);
184  }
185 
186  // add the identity element first
187  elements.emplace_back();
188 
190  for(const auto& g: generators) {
191  elements.push_back(g);
192  }
193 
194  // Generate the remaining elements in the group by multiplying by generators
195  for(unsigned int g = 1u; g < elements.size(); ++g) {
196  for(const auto& G: generators) {
197  Permutation e = elements[g] * G;
198  if(std::find(elements.cbegin(), elements.cend(), e) == elements.cend()) {
199  elements.emplace_back(std::move(e));
200  }
201  }
202  }
203 
204  sort(elements.begin(), elements.end());
205  }
206 
207  }; // class PermutationGroup
208 
210 
214  inline bool operator==(const PermutationGroup& p1, const PermutationGroup& p2) {
215  return (p1.order() == p2.order())
216  && p1.elements() == p2.elements();
217  }
218 
220 
225  inline bool operator!=(const PermutationGroup& p1, const PermutationGroup& p2) {
226  return ! operator==(p1, p2);
227  }
228 
230 
235  inline bool operator<(const PermutationGroup& p1, const PermutationGroup& p2) {
236  return std::lexicographical_compare(p1.cbegin(), p1.cend(),
237  p2.cbegin(), p2.cend());
238  }
239 
241 
245  inline std::ostream& operator<<(std::ostream& output, const PermutationGroup& p) {
246  output << "{";
247  for (auto i=p.cbegin(); i!=p.cend();) {
248  output << *i;
249  if (++i != p.cend())
250  output << ", ";
251  }
252  output << "}";
253  return output;
254  }
255 
256 
258 
261  class SymmetricGroup final: public PermutationGroup {
262  public:
264 
265  // Compiler generated functions
266  SymmetricGroup() = delete;
267  SymmetricGroup(const SymmetricGroup&) = default;
268  SymmetricGroup(SymmetricGroup&&) = default;
269  SymmetricGroup& operator=(const SymmetricGroup&) = default;
271 
274  SymmetricGroup(unsigned int degree) :
275  SymmetricGroup(SymmetricGroup::iota_vector(degree))
276  {
277  }
278 
283  template <typename InputIterator,
284  typename std::enable_if< ::TiledArray::detail::is_input_iterator<InputIterator>::value>::type* = nullptr>
285  SymmetricGroup(InputIterator begin, InputIterator end) :
286  PermutationGroup(), domain_(begin, end)
287  {
288  for(auto iter=begin; iter!=end; ++iter) {
289  TA_ASSERT(*iter >= 0);
290  }
291 
292  const auto degree = domain_.size();
293 
294  // Add generators to the list of elements
295  if(degree > 2u) {
296  for(unsigned int i = 0u; i < degree; ++i) {
297  // Construct the generator and add to the list
298  unsigned int i1 = (i + 1u) % degree;
299  generators_.emplace_back(Permutation::Map{{domain_[i],domain_[i1]},{domain_[i1],domain_[i]}});
300  }
301  } else if(degree == 2u) {
302  // Construct the generator
303  generators_.emplace_back(Permutation::Map{{domain_[0], domain_[1]}, {domain_[1], domain_[0]}});
304  }
305 
307  }
308 
310 
313  template <typename Integer,
314  typename std::enable_if<std::is_integral<Integer>::value>::type* = nullptr>
315  explicit SymmetricGroup(std::initializer_list<Integer> list) :
316  SymmetricGroup(list.begin(), list.end())
317  {
318  }
319 
321 
324  unsigned int degree() const { return domain_.size(); }
325 
326  private:
327  std::vector<index_type> domain_;
328 
330  static std::vector<index_type> iota_vector(size_t n) {
331  std::vector<index_type> result(n);
332  std::iota(result.begin(), result.end(), 0);
333  return result;
334  }
335 
336  SymmetricGroup(const std::vector<index_type>& domain) :
338  {
339  }
340 
341 
342  };
343 
352  template <typename MultiIndex>
353  bool is_lexicographically_smallest(const MultiIndex& idx,
354  const PermutationGroup& pg) {
355  const auto idx_size = idx.size();
356  for(const auto& p: pg) {
357  for(size_t i=0; i!=idx_size; ++i) {
358  auto idx_i = idx[i];
359  auto idx_p_i = idx[p[i]];
360  if (idx_p_i < idx_i)
361  return false;
362  if (idx_p_i > idx_i)
363  break;
364  }
365  }
366  return true;
367  }
368 
370 
382  std::vector<PermutationGroup::Permutation> conjugate_generators;
383  const auto h_inv = h.inv();
384  for(const auto& generator: G.generators()) {
385  conjugate_generators.emplace_back(h * generator * h_inv);
386  }
387  return PermutationGroup{std::move(conjugate_generators)};
388  }
389 
396  std::vector<PermutationGroup::Permutation> intersect_elements;
397  std::set_intersection(G1.begin(), G1.end(),
398  G2.begin(), G2.end(),
399  std::back_inserter(intersect_elements));
400  return PermutationGroup{std::move(intersect_elements)};
401  }
402 
404 
409  template <typename Set>
410  inline PermutationGroup
411  stabilizer(const PermutationGroup& G, const Set& f) {
412  std::vector<PermutationGroup::Permutation> stabilizer_generators;
413  for(const auto& generator: G.generators()) {
414  bool fixes_set = true;
415  for (const auto& i: f) {
416  if (generator.is_in_domain(i)) {
417  fixes_set = false;
418  break;
419  }
420  }
421  if (fixes_set)
422  stabilizer_generators.push_back(generator);
423  }
424  return PermutationGroup{std::move(stabilizer_generators)};
425  }
426 
429  } // namespace symmetry
430 } // namespace TiledArray
431 
432 #endif // TILEDARRAY_SYMM_PERMUTATION_GROUP_H__INCLUDED
TiledArray::symmetry::Permutation Permutation
unsigned int order() const
Group order accessor.
SymmetricGroup(std::initializer_list< Integer > list)
Construct symmetric group using domain as an initializer list.
static void init(std::vector< Permutation > &generators, std::vector< Permutation > &elements)
PermutationGroup conjugate(const PermutationGroup &G, const PermutationGroup::Permutation &h)
Computes conjugate permutation group obtained by the action of a permutation.
PermutationGroup intersect(const PermutationGroup &G1, const PermutationGroup &G2)
Permutation inv() const
Construct the inverse of this permutation.
Definition: permutation.h:399
bool is_lexicographically_smallest(const MultiIndex &idx, const PermutationGroup &pg)
static Permutation identity()
Idenity element accessor.
STL namespace.
std::vector< Permutation >::const_iterator begin() const
forward iterator over the group elements pointing to the first element
const std::vector< Permutation > & elements() const
Elements vector accessor.
std::vector< Permutation > generators_
Group generators.
std::vector< Permutation >::const_iterator end() const
forward iterator over the group elements pointing past the last element
PermutationGroup & operator=(const PermutationGroup &)=default
PermutationGroup(std::vector< Permutation > generators)
General constructor.
bool operator!=(const Permutation &p1, const Permutation &p2)
Permutation inequality operator.
Definition: permutation.h:481
#define TA_ASSERT(a)
Definition: error.h:107
std::vector< Permutation > elements_
Group elements.
std::ostream & operator<<(std::ostream &output, const Permutation &p)
Add permutation to an output stream.
Definition: permutation.h:502
SymmetricGroup & operator=(const SymmetricGroup &)=default
PermutationGroup stabilizer(const PermutationGroup &G, const Set &f)
Computes the largest subgroup of a permutation group that leaves the given set of indices fixed...
bool operator==(const Permutation &p1, const Permutation &p2)
Permutation equality operator.
Definition: permutation.h:470
std::vector< Permutation >::const_iterator cend() const
forward iterator over the group elements pointing past the last element
unsigned int degree() const
Degree accessor.
SymmetricGroup(InputIterator begin, InputIterator end)
const Permutation & operator[](unsigned int i) const
Group element accessor.
std::vector< Permutation >::const_iterator cbegin() const
forward iterator over the group elements pointing to the first element
bool operator<(const Permutation &p1, const Permutation &p2)
Permutation less-than operator.
Definition: permutation.h:491
const std::vector< Permutation > & generators() const
Generators vector accessor.
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:141
std::map< index_type, index_type > Map
Definition: permutation.h:145
Set domain() const
Computes the domain of this group.