3 * Implementation of GiNaC's symmetry definitions. */
6 * GiNaC Copyright (C) 1999-2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "numeric.h" // for factorial()
30 #include "operators.h"
37 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(symmetry, basic,
38 print_func<print_context>(&symmetry::do_print).
39 print_func<print_tree>(&symmetry::do_print_tree))
42 Some notes about the structure of a symmetry tree:
43 - The leaf nodes of the tree are of type "none", have one index, and no
44 children (of course). They are constructed by the symmetry(unsigned)
46 - Leaf nodes are the only nodes that only have one index.
47 - Container nodes contain two or more children. The "indices" set member
48 is the set union of the index sets of all children, and the "children"
49 vector stores the children themselves.
50 - The index set of each child of a "symm", "anti" or "cycl" node must
51 have the same size. It follows that the children of such a node are
52 either all leaf nodes, or all container nodes with two or more indices.
56 // default constructor
59 symmetry::symmetry() : type(none)
61 tinfo_key = TINFO_symmetry;
68 symmetry::symmetry(unsigned i) : type(none)
71 tinfo_key = TINFO_symmetry;
74 symmetry::symmetry(symmetry_type t, const symmetry &c1, const symmetry &c2) : type(t)
77 tinfo_key = TINFO_symmetry;
84 /** Construct object from archive_node. */
85 symmetry::symmetry(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
88 if (!(n.find_unsigned("type", t)))
89 throw (std::runtime_error("unknown symmetry type in archive"));
90 type = (symmetry_type)t;
95 if (n.find_ex("child", e, sym_lst, i))
96 add(ex_to<symmetry>(e));
105 if (n.find_unsigned("index", u, i))
114 /** Archive the object. */
115 void symmetry::archive(archive_node &n) const
117 inherited::archive(n);
119 n.add_unsigned("type", type);
121 if (children.empty()) {
122 std::set<unsigned>::const_iterator i = indices.begin(), iend = indices.end();
124 n.add_unsigned("index", *i);
128 exvector::const_iterator i = children.begin(), iend = children.end();
130 n.add_ex("child", *i);
136 DEFAULT_UNARCHIVE(symmetry)
139 // functions overriding virtual functions from base classes
142 int symmetry::compare_same_type(const basic & other) const
144 GINAC_ASSERT(is_a<symmetry>(other));
146 // All symmetry trees are equal. They are not supposed to appear in
147 // ordinary expressions anyway...
151 void symmetry::do_print(const print_context & c, unsigned level) const
153 if (children.empty()) {
154 if (indices.size() > 0)
155 c.s << *(indices.begin());
160 case none: c.s << '!'; break;
161 case symmetric: c.s << '+'; break;
162 case antisymmetric: c.s << '-'; break;
163 case cyclic: c.s << '@'; break;
164 default: c.s << '?'; break;
167 size_t num = children.size();
168 for (size_t i=0; i<num; i++) {
169 children[i].print(c);
177 void symmetry::do_print_tree(const print_tree & c, unsigned level) const
179 c.s << std::string(level, ' ') << class_name()
180 << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
184 case none: c.s << "none"; break;
185 case symmetric: c.s << "symm"; break;
186 case antisymmetric: c.s << "anti"; break;
187 case cyclic: c.s << "cycl"; break;
188 default: c.s << "<unknown>"; break;
191 c.s << ", indices=(";
192 if (!indices.empty()) {
193 std::set<unsigned>::const_iterator i = indices.begin(), end = indices.end();
201 exvector::const_iterator i = children.begin(), end = children.end();
203 i->print(c, level + c.delta_indent);
209 // non-virtual functions in this class
212 symmetry &symmetry::add(const symmetry &c)
214 // All children must have the same number of indices
215 if (type != none && !children.empty()) {
216 GINAC_ASSERT(is_exactly_a<symmetry>(children[0]));
217 if (ex_to<symmetry>(children[0]).indices.size() != c.indices.size())
218 throw (std::logic_error("symmetry:add(): children must have same number of indices"));
221 // Compute union of indices and check whether the two sets are disjoint
222 std::set<unsigned> un;
223 set_union(indices.begin(), indices.end(), c.indices.begin(), c.indices.end(), inserter(un, un.begin()));
224 if (un.size() != indices.size() + c.indices.size())
225 throw (std::logic_error("symmetry::add(): the same index appears in more than one child"));
231 children.push_back(c);
235 void symmetry::validate(unsigned n)
237 if (indices.upper_bound(n - 1) != indices.end())
238 throw (std::range_error("symmetry::verify(): index values are out of range"));
239 if (type != none && indices.empty()) {
240 for (unsigned i=0; i<n; i++)
249 class sy_is_less : public std::binary_function<ex, ex, bool> {
250 exvector::iterator v;
253 sy_is_less(exvector::iterator v_) : v(v_) {}
255 bool operator() (const ex &lh, const ex &rh) const
257 GINAC_ASSERT(is_exactly_a<symmetry>(lh));
258 GINAC_ASSERT(is_exactly_a<symmetry>(rh));
259 GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
260 std::set<unsigned>::const_iterator ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
261 while (ait != aitend) {
262 int cmpval = v[*ait].compare(v[*bit]);
273 class sy_swap : public std::binary_function<ex, ex, void> {
274 exvector::iterator v;
279 sy_swap(exvector::iterator v_, bool &s) : v(v_), swapped(s) {}
281 void operator() (const ex &lh, const ex &rh)
283 GINAC_ASSERT(is_exactly_a<symmetry>(lh));
284 GINAC_ASSERT(is_exactly_a<symmetry>(rh));
285 GINAC_ASSERT(ex_to<symmetry>(lh).indices.size() == ex_to<symmetry>(rh).indices.size());
286 std::set<unsigned>::const_iterator ait = ex_to<symmetry>(lh).indices.begin(), aitend = ex_to<symmetry>(lh).indices.end(), bit = ex_to<symmetry>(rh).indices.begin();
287 while (ait != aitend) {
288 v[*ait].swap(v[*bit]);
295 int canonicalize(exvector::iterator v, const symmetry &symm)
297 // Less than two elements? Then do nothing
298 if (symm.indices.size() < 2)
301 // Canonicalize children first
302 bool something_changed = false;
304 exvector::const_iterator first = symm.children.begin(), last = symm.children.end();
305 while (first != last) {
306 GINAC_ASSERT(is_exactly_a<symmetry>(*first));
307 int child_sign = canonicalize(v, ex_to<symmetry>(*first));
310 if (child_sign != INT_MAX) {
311 something_changed = true;
317 // Now reorder the children
318 first = symm.children.begin();
320 case symmetry::symmetric:
321 // Sort the children in ascending order
322 shaker_sort(first, last, sy_is_less(v), sy_swap(v, something_changed));
324 case symmetry::antisymmetric:
325 // Sort the children in ascending order, keeping track of the signum
326 sign *= permutation_sign(first, last, sy_is_less(v), sy_swap(v, something_changed));
330 case symmetry::cyclic:
331 // Permute the smallest child to the front
332 cyclic_permutation(first, last, min_element(first, last, sy_is_less(v)), sy_swap(v, something_changed));
337 return something_changed ? sign : INT_MAX;
341 // Symmetrize/antisymmetrize over a vector of objects
342 static ex symm(const ex & e, exvector::const_iterator first, exvector::const_iterator last, bool asymmetric)
344 // Need at least 2 objects for this operation
345 unsigned num = last - first;
349 // Transform object vector to a lst (for subs())
350 lst orig_lst(first, last);
352 // Create index vectors for permutation
353 unsigned *iv = new unsigned[num], *iv2;
354 for (unsigned i=0; i<num; i++)
356 iv2 = (asymmetric ? new unsigned[num] : NULL);
358 // Loop over all permutations (the first permutation, which is the
359 // identity, is unrolled)
361 while (std::next_permutation(iv, iv + num)) {
363 for (unsigned i=0; i<num; i++)
364 new_lst.append(orig_lst.op(iv[i]));
365 ex term = e.subs(orig_lst, new_lst, subs_options::no_pattern);
367 memcpy(iv2, iv, num * sizeof(unsigned));
368 term *= permutation_sign(iv2, iv2 + num);
376 return sum / factorial(numeric(num));
379 ex symmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last)
381 return symm(e, first, last, false);
384 ex antisymmetrize(const ex & e, exvector::const_iterator first, exvector::const_iterator last)
386 return symm(e, first, last, true);
389 ex symmetrize_cyclic(const ex & e, exvector::const_iterator first, exvector::const_iterator last)
391 // Need at least 2 objects for this operation
392 unsigned num = last - first;
396 // Transform object vector to a lst (for subs())
397 lst orig_lst(first, last);
398 lst new_lst = orig_lst;
400 // Loop over all cyclic permutations (the first permutation, which is
401 // the identity, is unrolled)
403 for (unsigned i=0; i<num-1; i++) {
404 ex perm = new_lst.op(0);
405 new_lst.remove_first().append(perm);
406 sum += e.subs(orig_lst, new_lst, subs_options::no_pattern);
411 /** Symmetrize expression over a list of objects (symbols, indices). */
412 ex ex::symmetrize(const lst & l) const
414 exvector v(l.begin(), l.end());
415 return symm(*this, v.begin(), v.end(), false);
418 /** Antisymmetrize expression over a list of objects (symbols, indices). */
419 ex ex::antisymmetrize(const lst & l) const
421 exvector v(l.begin(), l.end());
422 return symm(*this, v.begin(), v.end(), true);
425 /** Symmetrize expression by cyclic permutation over a list of objects
426 * (symbols, indices). */
427 ex ex::symmetrize_cyclic(const lst & l) const
429 exvector v(l.begin(), l.end());
430 return GiNaC::symmetrize_cyclic(*this, v.begin(), v.end());