Skip to content

Commit b02af61

Browse files
author
Dominic Price
committed
Fixed antisymmetrization issue
1 parent c2fdfaf commit b02af61

File tree

2 files changed

+75
-23
lines changed

2 files changed

+75
-23
lines changed

core/algorithms/young_reduce.cc

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,39 @@ std::string ex_to_string(cadabra::Ex::iterator it, const cadabra::Kernel& kernel
2626
return ex_to_string(cadabra::Ex(it), kernel);
2727
}
2828

29-
std::string adjform_to_string(const cadabra::yr::adjform_t& adjform, const std::vector<cadabra::nset_t::iterator>& index_map)
29+
std::string adjform_to_string(const cadabra::yr::adjform_t& adjform, const std::vector<cadabra::nset_t::iterator>* index_map = nullptr)
3030
{
3131
std::map<cadabra::yr::index_t, int> dummy_map;
3232
int dummy_counter = 0;
3333
std::string res;
3434
for (const auto& elem : adjform) {
35-
if (elem < 0) {
36-
res += *index_map[-(elem + 1)];
37-
}
38-
else if (dummy_map.find(elem) != dummy_map.end()) {
39-
res += "d_" + std::to_string(dummy_map[elem]);
35+
if (index_map) {
36+
if (elem < 0) {
37+
res += *(*index_map)[-(elem + 1)];
38+
}
39+
else if (dummy_map.find(elem) != dummy_map.end()) {
40+
res += "d_" + std::to_string(dummy_map[elem]);
41+
}
42+
else {
43+
dummy_map[adjform[adjform[elem]]] = dummy_counter++;
44+
res += "d_" + std::to_string(dummy_map[adjform[adjform[elem]]]);
45+
}
4046
}
4147
else {
42-
dummy_map[adjform[adjform[elem]]] = dummy_counter++;
43-
res += "d_" + std::to_string(dummy_map[adjform[adjform[elem]]]);
48+
res += std::to_string(elem);
4449
}
4550
}
4651
return res;
4752
}
4853

49-
std::string pf_to_string (const cadabra::yr::ProjectedForm& projform, const std::vector<cadabra::nset_t::iterator>& index_map)
54+
std::string pf_to_string (const cadabra::yr::ProjectedForm& projform, const std::vector<cadabra::nset_t::iterator>* index_map = nullptr)
5055
{
5156
std::stringstream os;
5257
int i = 0;
53-
int max = 20;
58+
int max = std::min(std::size_t(200), projform.data.size());
5459
auto it = projform.data.begin();
55-
while (i < max && i < projform.data.size()) {
56-
for (const auto& elem : it->first)
57-
os << elem << ' ';
60+
while (i < max) {
61+
os << adjform_to_string(it->first/*, index_map*/);
5862
os << '\t' << it->second << '\n';
5963
++i;
6064
++it;
@@ -65,12 +69,54 @@ std::string pf_to_string (const cadabra::yr::ProjectedForm& projform, const std:
6569
return os.str();
6670
}
6771

68-
#define DEBUG_OUTPUT 1
72+
#define DEBUG_OUTPUT 0
6973
#define cdebug if (!DEBUG_OUTPUT) {} else std::cerr
7074

7175

7276
////////////////////////////////////////////////////////////////////
7377

78+
// Get the next permutation of adjform and return the number of swaps
79+
// required for the transformation
80+
int next_perm(cadabra::yr::adjform_t& adjform)
81+
{
82+
int n = adjform.size();
83+
84+
// Find longest non-increasing suffix to get pivot
85+
int pivot = n - 2;
86+
while (pivot > -1) {
87+
if (adjform[pivot + 1] > adjform[pivot])
88+
break;
89+
--pivot;
90+
}
91+
92+
// Entire sequence is already sorted, return
93+
if (pivot == -1)
94+
return 0;
95+
96+
// Find rightmost element greater than pivot
97+
int idx = n - 1;
98+
while (idx > pivot) {
99+
if (adjform[idx] > adjform[pivot])
100+
break;
101+
--idx;
102+
}
103+
104+
// Swap with pivot
105+
std::swap(adjform[pivot], adjform[idx]);
106+
107+
// Reverse the suffix
108+
int swaps = 1;
109+
int maxswaps = (n - pivot - 1) / 2;
110+
for (int i = 0; i < maxswaps; ++i) {
111+
if (adjform[pivot + i + 1] != adjform[n - i - 1]) {
112+
std::swap(adjform[pivot + i + 1], adjform[n - i - 1]);
113+
++swaps;
114+
}
115+
}
116+
117+
return swaps;
118+
}
119+
74120
// Returns the position of 'val' between 'begin' and 'end', starting
75121
// the search at 'offset'
76122
template <typename It, typename T>
@@ -147,19 +193,23 @@ namespace cadabra {
147193
data[adjform] = value;
148194
}
149195

150-
void ProjectedForm::apply_young_symmetry(const std::vector<index_t>& indices, bool antisymmetric)
196+
void ProjectedForm::apply_young_symmetry(const adjform_t& indices, bool antisymmetric)
151197
{
152-
map_t old_data = data;
198+
map_t old_data;
199+
std::swap(old_data, data);
153200

154201
// Loop over all entries, for each one looping over all permutations
155202
// of the indices to be symmetrized and creating a new term for that
156203
// permutation; then add the new term to the list of entries
157204
for (const auto& kv : old_data) {
205+
206+
cdebug << "Applying young_symmetry " << (antisymmetric ? -kv.second : kv.second) << " * " << adjform_to_string(indices) << " to term " << adjform_to_string(kv.first) << '\n';
207+
158208
auto perm = indices;
159-
bool flip = false;
160209
int parity = 1;
161-
while (std::next_permutation(perm.begin(), perm.end())) {
162-
if (antisymmetric && (flip = !flip))
210+
int swaps = 2;
211+
do {
212+
if (antisymmetric && swaps % 2 != 0)
163213
parity *= -1;
164214
auto ret = kv.first;
165215
for (size_t i = 0; i < indices.size(); ++i) {
@@ -169,8 +219,9 @@ namespace cadabra {
169219
if (ret[index] >= 0)
170220
ret[ret[index]] = index;
171221
}
222+
cdebug << "\tMade term " << adjform_to_string(ret) << " * " << (parity * kv.second) << '\n';
172223
data[ret] += parity * kv.second;
173-
}
224+
} while (swaps = next_perm(perm));
174225
}
175226
}
176227

@@ -539,7 +590,7 @@ ProjectedForm young_reduce::symmetrize(Ex::iterator it)
539590

540591
sym.multiply(*it->multiplier);
541592

542-
cdebug << sym << '\n';
593+
cdebug << pf_to_string(sym, &index_map) << '\n';
543594

544595
return sym;
545596
}

tests/youngreduce.cdb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ def test01():
66
S_{a b c}::Symmetric;
77
ex:= S_{a b c}S_{b a c} + S_{b a c}S_{c a b}:
88
young_reduce(ex, $S_{a b c}S_{a b c}$)
9+
display(ex)
910
assert(ex == $2S_{a b c}S_{a b c}$)
1011
print("Test 01 passed")
1112

@@ -158,8 +159,8 @@ def test15():
158159
R_{a b c d}::RiemannTensor.
159160
A_{a b c d}::AntiSymmetric.
160161
ex := R_{b a c d}:
161-
young_reduce(ex, $A_{b a c d})
162-
assert ex == $R_{b a c d}
162+
young_reduce(ex, $A_{b a c d}$)
163+
assert ex == $R_{b a c d}$
163164
print("Test 15 passed")
164165

165166
test15()

0 commit comments

Comments
 (0)