DEFAULT_UNARCHIVE(indexed)
//////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
//////////
void indexed::print(const print_context & c, unsigned level) const
<< std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
<< ", " << seq.size()-1 << " indices"
<< ", symmetry=" << symtree << std::endl;
- c.s << std::endl;
unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
seq[0].print(c, level + delta_indent);
printindices(c, level + delta_indent);
}
}
+/** Implementation of ex::diff() for an indexed object always returns 0.
+ *
+ * @see ex::diff */
+ex indexed::derivative(const symbol & s) const
+{
+ return _ex0();
+}
+
//////////
// global functions
//////////
* by the function */
static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, exvector & local_dummy_indices)
{
- int global_size = global_dummy_indices.size(),
- local_size = local_dummy_indices.size();
+ unsigned global_size = global_dummy_indices.size(),
+ local_size = local_dummy_indices.size();
// Any local dummy indices at all?
if (local_size == 0)
// More local indices than we encountered before, add the new ones
// to the global set
+ int old_global_size = global_size;
int remaining = local_size - global_size;
exvector::const_iterator it = local_dummy_indices.begin(), itend = local_dummy_indices.end();
while (it != itend && remaining > 0) {
}
it++;
}
- }
+ shaker_sort(global_dummy_indices.begin(), global_dummy_indices.end(), ex_is_less(), ex_swap());
- // Replace index symbols in expression
- GINAC_ASSERT(local_size <= global_size);
- bool all_equal = true;
- lst local_syms, global_syms;
- for (unsigned i=0; i<local_size; i++) {
- ex loc_sym = local_dummy_indices[i].op(0);
- ex glob_sym = global_dummy_indices[i].op(0);
- if (!loc_sym.is_equal(glob_sym)) {
- all_equal = false;
- local_syms.append(loc_sym);
- global_syms.append(glob_sym);
- }
+ // If this is the first set of local indices, do nothing
+ if (old_global_size == 0)
+ return e;
}
- if (all_equal)
+ GINAC_ASSERT(local_size <= global_size);
+
+ // Construct lists of index symbols
+ exlist local_syms, global_syms;
+ for (unsigned i=0; i<local_size; i++)
+ local_syms.push_back(local_dummy_indices[i].op(0));
+ shaker_sort(local_syms.begin(), local_syms.end(), ex_is_less(), ex_swap());
+ for (unsigned i=0; i<global_size; i++)
+ global_syms.push_back(global_dummy_indices[i].op(0));
+
+ // Remove common indices
+ exlist local_uniq, global_uniq;
+ set_difference(local_syms.begin(), local_syms.end(), global_syms.begin(), global_syms.end(), std::back_insert_iterator<exlist>(local_uniq), ex_is_less());
+ set_difference(global_syms.begin(), global_syms.end(), local_syms.begin(), local_syms.end(), std::back_insert_iterator<exlist>(global_uniq), ex_is_less());
+
+ // Replace remaining non-common local index symbols by global ones
+ if (local_uniq.empty())
return e;
- else
- return e.subs(local_syms, global_syms);
+ else {
+ while (global_uniq.size() > local_uniq.size())
+ global_uniq.pop_back();
+ return e.subs(lst(local_uniq), lst(global_uniq));
+ }
}
/** Simplify product of indexed expressions (commutative, noncommutative and
v.push_back(e.op(0));
v.push_back(e.op(0));
} else {
- for (int i=0; i<e.nops(); i++) {
+ for (unsigned i=0; i<e.nops(); i++) {
ex f = e.op(i);
if (is_ex_exactly_of_type(f, power) && f.op(1).is_equal(_ex2())) {
v.push_back(f.op(0));
} else if (is_ex_exactly_of_type(f, ncmul)) {
// Noncommutative factor found, split it as well
non_commutative = true; // everything becomes noncommutative, ncmul will sort out the commutative factors later
- for (int j=0; j<f.nops(); j++)
+ for (unsigned j=0; j<f.nops(); j++)
v.push_back(f.op(j));
} else
v.push_back(f);
// Check whether the two factors share dummy indices
exvector free, dummy;
find_free_and_dummy(un, free, dummy);
- if (dummy.size() == 0)
+ unsigned num_dummies = dummy.size();
+ if (num_dummies == 0)
continue;
// At least one dummy index, is it a defined scalar product?
bool contracted = false;
- if (free.size() == 0) {
+ if (free.empty()) {
if (sp.is_defined(*it1, *it2)) {
*it1 = sp.evaluate(*it1, *it2);
*it2 = _ex1();
}
}
- // Contraction of symmetric with antisymmetric object is zero
- if (dummy.size() > 1
- && ex_to<symmetry>(ex_to<indexed>(*it1).symtree).has_symmetry()
- && ex_to<symmetry>(ex_to<indexed>(*it2).symtree).has_symmetry()) {
-
- // Check all pairs of dummy indices
- for (unsigned idx1=0; idx1<dummy.size()-1; idx1++) {
- for (unsigned idx2=idx1+1; idx2<dummy.size(); idx2++) {
-
- // Try and swap the index pair and check whether the
- // relative sign changed
- lst subs_lst(dummy[idx1].op(0), dummy[idx2].op(0)), repl_lst(dummy[idx2].op(0), dummy[idx1].op(0));
- ex swapped1 = it1->subs(subs_lst, repl_lst);
- ex swapped2 = it2->subs(subs_lst, repl_lst);
- if (it1->is_equal(swapped1) && it2->is_equal(-swapped2)
- || it1->is_equal(-swapped1) && it2->is_equal(swapped2)) {
- free_indices.clear();
- return _ex0();
- }
- }
- }
- }
-
// Try to contract the first one with the second one
contracted = it1->op(0).bp->contract_with(it1, it2, v);
if (!contracted) {
else
r = e;
+ // The result should be symmetric with respect to exchange of dummy
+ // indices, so if the symmetrization vanishes, the whole expression is
+ // zero. This detects things like eps.i.j.k * p.j * p.k = 0.
+ if (local_dummy_indices.size() >= 2) {
+ lst dummy_syms;
+ for (int i=0; i<local_dummy_indices.size(); i++)
+ dummy_syms.append(local_dummy_indices[i].op(0));
+ if (r.symmetrize(dummy_syms).is_zero()) {
+ free_indices.clear();
+ return _ex0();
+ }
+ }
+
// Dummy index renaming
r = rename_dummy_indices(r, dummy_indices, local_dummy_indices);
void scalar_products::debugprint(void) const
{
std::cerr << "map size=" << spm.size() << std::endl;
- for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) {
- const spmapkey & k = cit->first;
+ spmap::const_iterator i = spm.begin(), end = spm.end();
+ while (i != end) {
+ const spmapkey & k = i->first;
std::cerr << "item key=(" << k.first << "," << k.second;
- std::cerr << "), value=" << cit->second << std::endl;
+ std::cerr << "), value=" << i->second << std::endl;
+ ++i;
}
}