3 * Interface to GiNaC's symmetry definitions. */
6 * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef GINAC_SYMMETRY_H
24 #define GINAC_SYMMETRY_H
36 /** This class describes the symmetry of a group of indices. These objects
37 * can be grouped into a tree to form complex mixed symmetries. */
38 class symmetry : public basic
40 friend class sy_is_less;
42 friend int canonicalize(exvector::iterator v, const symmetry &symm);
44 GINAC_DECLARE_REGISTERED_CLASS(symmetry, basic)
48 /** Type of symmetry */
50 none, /**< no symmetry properties */
51 symmetric, /**< totally symmetric */
52 antisymmetric, /**< totally antisymmetric */
53 cyclic /**< cyclic symmetry */
58 /** Create leaf node that represents one index. */
61 /** Create node with two children. */
62 symmetry(symmetry_type t, const symmetry &c1, const symmetry &c2);
64 // functions overriding virtual functions from base classes
66 /** Save (a.k.a. serialize) object into archive. */
67 void archive(archive_node& n) const override;
68 /** Read (a.k.a. deserialize) object from archive. */
69 void read_archive(const archive_node& n, lst& syms) override;
71 unsigned calchash() const override;
73 // non-virtual functions in this class
75 /** Get symmetry type. */
76 symmetry_type get_type() const {return type;}
78 /** Set symmetry type. */
79 void set_type(symmetry_type t) {type = t;}
81 /** Add child node, check index sets for consistency. */
82 symmetry &add(const symmetry &c);
84 /** Verify that all indices of this node are in the range [0..n-1].
85 * This function throws an exception if the verification fails.
86 * If the top node has a type != none and no children, add all indices
87 * in the range [0..n-1] as children. */
88 void validate(unsigned n);
90 /** Check whether this node actually represents any kind of symmetry. */
91 bool has_symmetry() const {return type != none || !children.empty(); }
92 /** Check whether this node involves anything non symmetric. */
93 bool has_nonsymmetric() const;
94 /** Check whether this node involves a cyclic symmetry. */
95 bool has_cyclic() const;
97 void do_print(const print_context & c, unsigned level) const;
98 void do_print_tree(const print_tree & c, unsigned level) const;
102 /** Type of symmetry described by this node. */
105 /** Sorted union set of all indices handled by this node. */
106 std::set<unsigned> indices;
108 /** Vector of child nodes. */
111 GINAC_DECLARE_UNARCHIVER(symmetry);
116 inline symmetry sy_none() { return symmetry(); }
117 inline symmetry sy_none(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::none, c1, c2); }
118 inline symmetry sy_none(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::none, c1, c2).add(c3); }
119 inline symmetry sy_none(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::none, c1, c2).add(c3).add(c4); }
121 inline symmetry sy_symm() { symmetry s; s.set_type(symmetry::symmetric); return s; }
122 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::symmetric, c1, c2); }
123 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::symmetric, c1, c2).add(c3); }
124 inline symmetry sy_symm(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::symmetric, c1, c2).add(c3).add(c4); }
126 inline symmetry sy_anti() { symmetry s; s.set_type(symmetry::antisymmetric); return s; }
127 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::antisymmetric, c1, c2); }
128 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::antisymmetric, c1, c2).add(c3); }
129 inline symmetry sy_anti(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::antisymmetric, c1, c2).add(c3).add(c4); }
131 inline symmetry sy_cycl() { symmetry s; s.set_type(symmetry::cyclic); return s; }
132 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2) { return symmetry(symmetry::cyclic, c1, c2); }
133 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2, const symmetry &c3) { return symmetry(symmetry::cyclic, c1, c2).add(c3); }
134 inline symmetry sy_cycl(const symmetry &c1, const symmetry &c2, const symmetry &c3, const symmetry &c4) { return symmetry(symmetry::cyclic, c1, c2).add(c3).add(c4); }
136 // These return references to preallocated common symmetries (similar to
137 // the numeric flyweights).
138 const symmetry & not_symmetric();
139 const symmetry & symmetric2();
140 const symmetry & symmetric3();
141 const symmetry & symmetric4();
142 const symmetry & antisymmetric2();
143 const symmetry & antisymmetric3();
144 const symmetry & antisymmetric4();
146 /** Canonicalize the order of elements of an expression vector, according to
147 * the symmetry properties defined in a symmetry tree.
149 * @param v Start of expression vector
150 * @param symm Root node of symmetry tree
151 * @return the overall sign introduced by the reordering (+1, -1 or 0)
152 * or numeric_limits<int>::max() if nothing changed */
153 extern int canonicalize(exvector::iterator v, const symmetry &symm);
155 /** Symmetrize expression over a set of objects (symbols, indices). */
156 ex symmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
158 /** Symmetrize expression over a set of objects (symbols, indices). */
159 inline ex symmetrize(const ex & e, const exvector & v)
161 return symmetrize(e, v.begin(), v.end());
164 /** Antisymmetrize expression over a set of objects (symbols, indices). */
165 ex antisymmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
167 /** Antisymmetrize expression over a set of objects (symbols, indices). */
168 inline ex antisymmetrize(const ex & e, const exvector & v)
170 return antisymmetrize(e, v.begin(), v.end());
173 /** Symmetrize expression by cyclic permutation over a set of objects
174 * (symbols, indices). */
175 ex symmetrize_cyclic(const ex & e, exvector::const_iterator first, exvector::const_iterator last);
177 /** Symmetrize expression by cyclic permutation over a set of objects
178 * (symbols, indices). */
179 inline ex symmetrize_cyclic(const ex & e, const exvector & v)
181 return symmetrize(e, v.begin(), v.end());
186 #endif // ndef GINAC_SYMMETRY_H