Eigen-Contrib  5.0.1
 
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
12#define EIGEN_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
13
14// IWYU pragma: private
15#include "../InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21namespace group_theory {
22
34
35/**********************************************************************
36 * "Ok kid, here is where it gets complicated."
37 * - Amelia Pond in the "Doctor Who" episode
38 * "The Big Bang"
39 *
40 * Dimino's algorithm
41 * ==================
42 *
43 * The following is Dimino's algorithm in sequential form:
44 *
45 * Input: identity element, list of generators, equality check,
46 * multiplication operation
47 * Output: list of group elements
48 *
49 * 1. add identity element
50 * 2. remove identities from list of generators
51 * 3. add all powers of first generator that aren't the
52 * identity element
53 * 4. go through all remaining generators:
54 * a. if generator is already in the list of elements
55 * -> do nothing
56 * b. otherwise
57 * i. remember current # of elements
58 * (i.e. the size of the current subgroup)
59 * ii. add all current elements (which includes
60 * the identity) each multiplied from right
61 * with the current generator to the group
62 * iii. add all remaining cosets that are generated
63 * by products of the new generator with itself
64 * and all other generators seen so far
65 *
66 * In functional form, this is implemented as a long set of recursive
67 * templates that have a complicated relationship.
68 *
69 * The main interface for Dimino's algorithm is the template
70 * enumerate_group_elements. All lists are implemented as variadic
71 * type_list<typename...> and std::integer_sequence<int, ...>
72 * templates.
73 *
74 * 'Calling' templates is usually done via typedefs.
75 *
76 * This algorithm is an extended version of the basic version. The
77 * extension consists in the fact that each group element has a set
78 * of flags associated with it. Multiplication of two group elements
79 * with each other results in a group element whose flags are the
80 * XOR of the flags of the previous elements. Each time the algorithm
81 * notices that a group element it just calculated is already in the
82 * list of current elements, the flags of both will be compared and
83 * added to the so-called 'global flags' of the group.
84 *
85 * The rationale behind this extension is that this allows not only
86 * for the description of symmetries between tensor indices, but
87 * also allows for the description of hermiticity, antisymmetry and
88 * antihermiticity. Negation and conjugation each are specific bit
89 * in the flags value and if two different ways to reach a group
90 * element lead to two different flags, this poses a constraint on
91 * the allowed values of the resulting tensor. For example, if a
92 * group element is reached both with and without the conjugation
93 * flags, it is clear that the resulting tensor has to be real.
94 *
95 * Note that this flag mechanism is quite generic and may have other
96 * uses beyond tensor properties.
97 *
98 * IMPORTANT:
99 * This algorithm assumes the group to be finite. If you try to
100 * run it with a group that's infinite, the algorithm will only
101 * terminate once you hit a compiler limit (max template depth).
102 * Also note that trying to use this implementation to create a
103 * very large group will probably either make you hit the same
104 * limit, cause the compiler to segfault or at the very least
105 * take a *really* long time (hours, days, weeks - sic!) to
106 * compile. It is not recommended to plug in more than 4
107 * generators, unless they are independent of each other.
108 */
109
123template <template <typename, typename> class Equality, typename id, typename L>
124struct strip_identities;
125
126template <template <typename, typename> class Equality, typename id, typename t, typename... ts>
127struct strip_identities<Equality, id, type_list<t, ts...>> {
128 typedef std::conditional_t<
129 Equality<id, t>::value, typename strip_identities<Equality, id, type_list<ts...>>::type,
130 typename concat<type_list<t>, typename strip_identities<Equality, id, type_list<ts...>>::type>::type>
131 type;
132 constexpr static int global_flags =
133 Equality<id, t>::global_flags | strip_identities<Equality, id, type_list<ts...>>::global_flags;
134};
135
136template <template <typename, typename> class Equality, typename id>
137struct strip_identities<Equality, id, type_list<>> {
138 typedef type_list<> type;
139 constexpr static int global_flags = 0;
140};
141
155template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
156 typename g, typename current_element, typename elements,
157 bool dont_add_current_element // = false
158 >
159struct dimino_first_step_elements_helper
160#ifndef EIGEN_PARSED_BY_DOXYGEN
161 : // recursive inheritance is too difficult for Doxygen
162 public dimino_first_step_elements_helper<Multiply, Equality, id, g, typename Multiply<current_element, g>::type,
163 typename concat<elements, type_list<current_element>>::type,
164 Equality<typename Multiply<current_element, g>::type, id>::value> {
165};
166
167template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
168 typename g, typename current_element, typename elements>
169struct dimino_first_step_elements_helper<Multiply, Equality, id, g, current_element, elements, true>
170#endif // EIGEN_PARSED_BY_DOXYGEN
171{
172 typedef elements type;
173 constexpr static int global_flags = Equality<current_element, id>::global_flags;
174};
175
189template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
190 typename generators>
191struct dimino_first_step_elements {
192 typedef typename get<0, generators>::type first_generator;
193 typedef typename skip<1, generators>::type next_generators;
194 typedef type_list<first_generator> generators_done;
195
196 typedef dimino_first_step_elements_helper<Multiply, Equality, id, first_generator, first_generator, type_list<id>,
197 false>
198 helper;
199 typedef typename helper::type type;
200 constexpr static int global_flags = helper::global_flags;
201};
202
223template <template <typename, typename> class Multiply, typename sub_group_elements, typename new_coset_rep,
224 bool generate_coset // = true
225 >
226struct dimino_get_coset_elements {
227 typedef typename apply_op_from_right<Multiply, new_coset_rep, sub_group_elements>::type type;
228};
229
230template <template <typename, typename> class Multiply, typename sub_group_elements, typename new_coset_rep>
231struct dimino_get_coset_elements<Multiply, sub_group_elements, new_coset_rep, false> {
232 typedef type_list<> type;
233};
234
249template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
250 typename sub_group_elements, typename elements, typename generators, typename rep_element, int sub_group_size>
251struct dimino_add_cosets_for_rep;
252
253template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
254 typename sub_group_elements, typename elements, typename g, typename... gs, typename rep_element,
255 int sub_group_size>
256struct dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements, elements, type_list<g, gs...>, rep_element,
257 sub_group_size> {
258 typedef typename Multiply<rep_element, g>::type new_coset_rep;
259 typedef contained_in_list_gf<Equality, new_coset_rep, elements> _cil;
260 constexpr static bool add_coset = !_cil::value;
261
262 typedef
263 typename dimino_get_coset_elements<Multiply, sub_group_elements, new_coset_rep, add_coset>::type coset_elements;
264
265 typedef dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements,
266 typename concat<elements, coset_elements>::type, type_list<gs...>, rep_element,
267 sub_group_size>
268 _helper;
269
270 typedef typename _helper::type type;
271 constexpr static int global_flags = _cil::global_flags | _helper::global_flags;
272
273 /* Note that we don't have to update global flags here, since
274 * we will only add these elements if they are not part of
275 * the group already. But that only happens if the coset rep
276 * is not already in the group, so the check for the coset rep
277 * will catch this.
278 */
279};
280
281template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
282 typename sub_group_elements, typename elements, typename rep_element, int sub_group_size>
283struct dimino_add_cosets_for_rep<Multiply, Equality, id, sub_group_elements, elements, type_list<>, rep_element,
284 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
439 typedef dimino_add_remaining_generators<Multiply, Equality, id, typename first_step::generators_done,
440 typename first_step::next_generators, // remaining_generators
441 typename first_step::type // first_step elements
442 >
443 _helper;
444
445 typedef typename _helper::type type;
446 constexpr static int global_flags = initial_global_flags | first_step::global_flags | _helper::global_flags;
447};
448
449// in case when no generators are specified
450template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
451 int initial_global_flags>
452struct enumerate_group_elements_noid<Multiply, Equality, id, type_list<>, initial_global_flags> {
453 typedef type_list<id> type;
454 constexpr static int global_flags = initial_global_flags;
455};
456
474template <template <typename, typename> class Multiply, template <typename, typename> class Equality, typename id,
475 typename Generators_>
476struct enumerate_group_elements
477 : public enumerate_group_elements_noid<Multiply, Equality, id,
478 typename strip_identities<Equality, id, Generators_>::type,
479 strip_identities<Equality, id, Generators_>::global_flags> {};
480
481} // end namespace group_theory
482
483} // end namespace internal
484
485} // end namespace Eigen
486
487#endif // EIGEN_TENSORSYMMETRY_TEMPLATEGROUPTHEORY_H
488
489/*
490 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
491 */
Namespace containing all symbols from the Eigen library.