Eigen-unsupported  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
TemplateGroupTheory.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_CXX11_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
11#define EIGEN_CXX11_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
12
13// IWYU pragma: private
14#include "../InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19
20namespace group_theory {
21
33
34/**********************************************************************
35 * "Ok kid, here is where it gets complicated."
36 * - Amelia Pond in the "Doctor Who" episode
37 * "The Big Bang"
38 *
39 * Dimino's algorithm
40 * ==================
41 *
42 * The following is Dimino's algorithm in sequential form:
43 *
44 * Input: identity element, list of generators, equality check,
45 * multiplication operation
46 * Output: list of group elements
47 *
48 * 1. add identity element
49 * 2. remove identities from list of generators
50 * 3. add all powers of first generator that aren't the
51 * identity element
52 * 4. go through all remaining generators:
53 * a. if generator is already in the list of elements
54 * -> do nothing
55 * b. otherwise
56 * i. remember current # of elements
57 * (i.e. the size of the current subgroup)
58 * ii. add all current elements (which includes
59 * the identity) each multiplied from right
60 * with the current generator to the group
61 * iii. add all remaining cosets that are generated
62 * by products of the new generator with itself
63 * and all other generators seen so far
64 *
65 * In functional form, this is implemented as a long set of recursive
66 * templates that have a complicated relationship.
67 *
68 * The main interface for Dimino's algorithm is the template
69 * enumerate_group_elements. All lists are implemented as variadic
70 * type_list<typename...> and numeric_list<typename = int, int...>
71 * templates.
72 *
73 * 'Calling' templates is usually done via typedefs.
74 *
75 * This algorithm is an extended version of the basic version. The
76 * extension consists in the fact that each group element has a set
77 * of flags associated with it. Multiplication of two group elements
78 * with each other results in a group element whose flags are the
79 * XOR of the flags of the previous elements. Each time the algorithm
80 * notices that a group element it just calculated is already in the
81 * list of current elements, the flags of both will be compared and
82 * added to the so-called 'global flags' of the group.
83 *
84 * The rationale behind this extension is that this allows not only
85 * for the description of symmetries between tensor indices, but
86 * also allows for the description of hermiticity, antisymmetry and
87 * antihermiticity. Negation and conjugation each are specific bit
88 * in the flags value and if two different ways to reach a group
89 * element lead to two different flags, this poses a constraint on
90 * the allowed values of the resulting tensor. For example, if a
91 * group element is reach both with and without the conjugation
92 * flags, it is clear that the resulting tensor has to be real.
93 *
94 * Note that this flag mechanism is quite generic and may have other
95 * uses beyond tensor properties.
96 *
97 * IMPORTANT:
98 * This algorithm assumes the group to be finite. If you try to
99 * run it with a group that's infinite, the algorithm will only
100 * terminate once you hit a compiler limit (max template depth).
101 * Also note that trying to use this implementation to create a
102 * very large group will probably either make you hit the same
103 * limit, cause the compiler to segfault or at the very least
104 * take a *really* long time (hours, days, weeks - sic!) to
105 * compile. It is not recommended to plug in more than 4
106 * generators, unless they are independent of each other.
107 */
108
122template <template <typename, typename> class Equality, typename id, typename L>
123struct strip_identities;
124
125template <template <typename, typename> class Equality, typename id, typename t, typename... ts>
126struct strip_identities<Equality, id, type_list<t, ts...>> {
127 typedef std::conditional_t<
128 Equality<id, t>::value, typename strip_identities<Equality, id, type_list<ts...>>::type,
129 typename concat<type_list<t>, typename strip_identities<Equality, id, type_list<ts...>>::type>::type>
130 type;
131 constexpr static int global_flags =
132 Equality<id, t>::global_flags | strip_identities<Equality, id, type_list<ts...>>::global_flags;
133};
134
135template <template <typename, typename> class Equality, typename id EIGEN_TPL_PP_SPEC_HACK_DEFC(typename, ts)>
136struct strip_identities<Equality, id, type_list<EIGEN_TPL_PP_SPEC_HACK_USE(ts)>> {
137 typedef type_list<> type;
138 constexpr static int global_flags = 0;
139};
140
154template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
155 typename g, typename current_element, typename elements,
156 bool dont_add_current_element // = false
157 >
158struct dimino_first_step_elements_helper
159#ifndef EIGEN_PARSED_BY_DOXYGEN
160 : // recursive inheritance is too difficult for Doxygen
161 public dimino_first_step_elements_helper<Multiply, Equality, id, g, typename Multiply<current_element, g>::type,
162 typename concat<elements, type_list<current_element>>::type,
163 Equality<typename Multiply<current_element, g>::type, id>::value> {
164};
165
166template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
167 typename g, typename current_element, typename elements>
168struct dimino_first_step_elements_helper<Multiply, Equality, id, g, current_element, elements, true>
169#endif // EIGEN_PARSED_BY_DOXYGEN
170{
171 typedef elements type;
172 constexpr static int global_flags = Equality<current_element, id>::global_flags;
173};
174
188template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
189 typename generators>
190struct dimino_first_step_elements {
191 typedef typename get<0, generators>::type first_generator;
192 typedef typename skip<1, generators>::type next_generators;
193 typedef type_list<first_generator> generators_done;
194
195 typedef dimino_first_step_elements_helper<Multiply, Equality, id, first_generator, first_generator, type_list<id>,
196 false>
197 helper;
198 typedef typename helper::type type;
199 constexpr static int global_flags = helper::global_flags;
200};
201
222template <template <typename, typename> class Multiply, typename sub_group_elements, typename new_coset_rep,
223 bool generate_coset // = true
224 >
225struct dimino_get_coset_elements {
226 typedef typename apply_op_from_right<Multiply, new_coset_rep, sub_group_elements>::type type;
227};
228
229template <template <typename, typename> class Multiply, typename sub_group_elements, typename new_coset_rep>
230struct dimino_get_coset_elements<Multiply, sub_group_elements, new_coset_rep, false> {
231 typedef type_list<> type;
232};
233
248template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
249 typename sub_group_elements, typename elements, typename generators, typename rep_element, int sub_group_size>
250struct dimino_add_cosets_for_rep;
251
252template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
253 typename sub_group_elements, typename elements, typename g, typename... gs, typename rep_element,
254 int sub_group_size>
255struct dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements, elements, type_list<g, gs...>, rep_element,
256 sub_group_size> {
257 typedef typename Multiply<rep_element, g>::type new_coset_rep;
258 typedef contained_in_list_gf<Equality, new_coset_rep, elements> _cil;
259 constexpr static bool add_coset = !_cil::value;
260
261 typedef
262 typename dimino_get_coset_elements<Multiply, sub_group_elements, new_coset_rep, add_coset>::type coset_elements;
263
264 typedef dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements,
265 typename concat<elements, coset_elements>::type, type_list<gs...>, rep_element,
266 sub_group_size>
267 _helper;
268
269 typedef typename _helper::type type;
270 constexpr static int global_flags = _cil::global_flags | _helper::global_flags;
271
272 /* Note that we don't have to update global flags here, since
273 * we will only add these elements if they are not part of
274 * the group already. But that only happens if the coset rep
275 * is not already in the group, so the check for the coset rep
276 * will catch this.
277 */
278};
279
280template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
281 typename sub_group_elements, typename elements EIGEN_TPL_PP_SPEC_HACK_DEFC(typename, empty),
282 typename rep_element, int sub_group_size>
283struct dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements, elements,
284 type_list<EIGEN_TPL_PP_SPEC_HACK_USE(empty)>, rep_element, sub_group_size> {
285 typedef elements type;
286 constexpr static int global_flags = 0;
287};
288
303template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
304 typename sub_group_elements, typename elements, typename generators, int sub_group_size, int rep_pos,
305 bool stop_condition // = false
306 >
307struct dimino_add_all_coset_spaces {
308 typedef typename get<rep_pos, elements>::type rep_element;
309 typedef dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements, elements, generators, rep_element,
310 sub_group_elements::count>
311 _ac4r;
312 typedef typename _ac4r::type new_elements;
313
314 constexpr static int new_rep_pos = rep_pos + sub_group_elements::count;
315 constexpr static bool new_stop_condition = new_rep_pos >= new_elements::count;
316
317 typedef dimino_add_all_coset_spaces<Multiply, Equality, id, sub_group_elements, new_elements, generators,
318 sub_group_size, new_rep_pos, new_stop_condition>
319 _helper;
320
321 typedef typename _helper::type type;
322 constexpr static int global_flags = _helper::global_flags | _ac4r::global_flags;
323};
324
325template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
326 typename sub_group_elements, typename elements, typename generators, int sub_group_size, int rep_pos>
327struct dimino_add_all_coset_spaces<Multiply, Equality, id, sub_group_elements, elements, generators, sub_group_size,
328 rep_pos, true> {
329 typedef elements type;
330 constexpr static int global_flags = 0;
331};
332
345template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
346 typename elements, typename generators_done, typename current_generator,
347 bool redundant // = false
348 >
349struct dimino_add_generator {
350 /* this template is only called if the generator is not redundant
351 * => all elements of the group multiplied with the new generator
352 * are going to be new elements of the most trivial coset space
353 */
354 typedef typename apply_op_from_right<Multiply, current_generator, elements>::type multiplied_elements;
355 typedef typename concat<elements, multiplied_elements>::type new_elements;
356
357 constexpr static int rep_pos = elements::count;
358
359 typedef dimino_add_all_coset_spaces<
360 Multiply, Equality, id,
361 elements, // elements of previous subgroup
362 new_elements, typename concat<generators_done, type_list<current_generator>>::type,
363 elements::count, // size of previous subgroup
364 rep_pos,
365 false // don't stop (because rep_pos >= new_elements::count is always false at this point)
366 >
367 _helper;
368 typedef typename _helper::type type;
369 constexpr static int global_flags = _helper::global_flags;
370};
371
372template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
373 typename elements, typename generators_done, typename current_generator>
374struct dimino_add_generator<Multiply, Equality, id, elements, generators_done, current_generator, true> {
375 // redundant case
376 typedef elements type;
377 constexpr static int global_flags = 0;
378};
379
392template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
393 typename generators_done, typename remaining_generators, typename elements>
394struct dimino_add_remaining_generators {
395 typedef typename get<0, remaining_generators>::type first_generator;
396 typedef typename skip<1, remaining_generators>::type next_generators;
397
398 typedef contained_in_list_gf<Equality, first_generator, elements> _cil;
399
400 typedef dimino_add_generator<Multiply, Equality, id, elements, generators_done, first_generator, _cil::value> _helper;
401
402 typedef typename _helper::type new_elements;
403
404 typedef dimino_add_remaining_generators<Multiply, Equality, id,
405 typename concat<generators_done, type_list<first_generator>>::type,
406 next_generators, new_elements>
407 _next_iter;
408
409 typedef typename _next_iter::type type;
410 constexpr static int global_flags = _cil::global_flags | _helper::global_flags | _next_iter::global_flags;
411};
412
413template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
414 typename generators_done, typename elements>
415struct dimino_add_remaining_generators<Multiply, Equality, id, generators_done, type_list<>, elements> {
416 typedef elements type;
417 constexpr static int global_flags = 0;
418};
419
434template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
435 typename generators, int initial_global_flags = 0>
436struct enumerate_group_elements_noid {
437 typedef dimino_first_step_elements<Multiply, Equality, id, generators> first_step;
438 typedef typename first_step::type first_step_elements;
439
440 typedef dimino_add_remaining_generators<Multiply, Equality, id, typename first_step::generators_done,
441 typename first_step::next_generators, // remaining_generators
442 typename first_step::type // first_step elements
443 >
444 _helper;
445
446 typedef typename _helper::type type;
447 constexpr static int global_flags = initial_global_flags | first_step::global_flags | _helper::global_flags;
448};
449
450// in case when no generators are specified
451template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
452 int initial_global_flags>
453struct enumerate_group_elements_noid<Multiply, Equality, id, type_list<>, initial_global_flags> {
454 typedef type_list<id> type;
455 constexpr static int global_flags = initial_global_flags;
456};
457
475template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
476 typename Generators_>
477struct enumerate_group_elements
478 : public enumerate_group_elements_noid<Multiply, Equality, id,
479 typename strip_identities<Equality, id, Generators_>::type,
480 strip_identities<Equality, id, Generators_>::global_flags> {};
481
482} // end namespace group_theory
483
484} // end namespace internal
485
486} // end namespace Eigen
487
488#endif // EIGEN_CXX11_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
489
490/*
491 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
492 */
Namespace containing all symbols from the Eigen library.