File: young_project.cc

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (159 lines) | stat: -rw-r--r-- 4,595 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

#include "IndexIterator.hh"
#include "algorithms/young_project.hh"

using namespace cadabra;

young_project::young_project(const Kernel& k, Ex& tr)
	: Algorithm(k,tr), remove_traces(false)
	{
	// For internal use in which one fills the young tableau structures directly.
	}

young_project::young_project(const Kernel& k, Ex& tr,
                             const std::vector<int>& shape,
                             const std::vector<int>& indices)
	: Algorithm(k,tr), remove_traces(false)
	{
	int count=0;
	for(unsigned int row=0; row<shape.size(); ++row) {
		for(int col=0; col<shape[row]; ++col) {
			tab.add_box(row, indices[count]);
			++count;
			}
		}
	}

bool young_project::can_apply(iterator it)
	{
	if(*it->name!="\\prod") {
		if(!is_single_term(it)) {
			return false;
			}
		}

	prod_wrap_single_term(it);
	if(nametab.number_of_rows()>0) { // have to convert names to numbers
		tab.copy_shape(nametab);
		pos_tab_t::iterator pi=tab.begin();
		name_tab_t::iterator ni=nametab.begin();
		while(ni!=nametab.end()) {
			index_iterator ii=index_iterator::begin(kernel.properties, it);
			unsigned int indexnum=0;
			while(ii!=index_iterator::end(kernel.properties, it)) {
				if(subtree_exact_equal(&kernel.properties, ii, *ni)) {
					*pi=indexnum;
					break;
					}
				++indexnum;
				++ii;
				}
			if(indexnum==number_of_indices(kernel.properties, it)) {
				prod_unwrap_single_term(it);
				return false; // cannot find indicated index in expression
				}
			++pi;
			++ni;
			}
		}

	prod_unwrap_single_term(it);
	return true;
	}

Ex::iterator young_project::nth_index_node(iterator it, unsigned int num)
	{
	Ex::fixed_depth_iterator indname=tr.begin_fixed(it, 2);
	indname+=num;
	return indname;
	}

Algorithm::result_t young_project::apply(iterator& it)
	{
	prod_wrap_single_term(it);
	sym.clear();

	if(asym_ranges.size()>0) {
		// Convert index locations to box numbers.
		combin::range_vector_t sublengths_scattered;
		//		txtout << "asym_ranges: ";
		for(unsigned int i=0; i<asym_ranges.size(); ++i) {
			combin::range_t newr;
			for(unsigned int j=0; j<asym_ranges[i].size(); ++j) {
				// Search asym_ranges[i][j]
				int offs=0;
				pos_tab_t::iterator tt=tab.begin();
				while(tt!=tab.end()) {
					if((*tt)==asym_ranges[i][j]) {
						newr.push_back(offs);
						//						txtout << asym_ranges[i][j] << " ";
						break;
						}
					++tt;
					++offs;
					}
				}
			sublengths_scattered.push_back(newr);
			//			txtout << std::endl;
			}
		tab.projector(sym, sublengths_scattered);
		}
	else tab.projector(sym);

	// FIXME: We can also compress the result by sorting all
	// locations which belong to the same asym set. This could actually
	// be done in combinatorics already.

	Ex rep;
	rep.set_head(str_node("\\sum"));
	for(unsigned int i=0; i<sym.size(); ++i) {
		// Generate the term.
		Ex repfac(it);
		for(unsigned int j=0; j<sym[i].size(); ++j) {
			index_iterator src_fd=index_iterator::begin(kernel.properties, it);
			index_iterator dst_fd=index_iterator::begin(kernel.properties, repfac.begin());
			src_fd+=sym[i][j];        // take the index at location sym[i][j]
			dst_fd+=sym.original[j];  // and store it in location sym.original[j]
			tr.replace_index(dst_fd, src_fd);
			}
		// Remove traces of antisymmetric objects. This can really
		// only be done here, since combinatorics.hh does not know
		// about index values, only about index locations. Note: we also
		// have to remove the entry in sym.original & sym.multiplicity if
		// we decide that a term vanishes.
		// IMPORTANT: if there are still permutations by value to be
		// done afterwards, do not use this!
		if(remove_traces) {
			for(unsigned int k=0; k<asym_ranges.size(); ++k) {
				for(unsigned int kk=0; kk<asym_ranges[k].size(); ++kk) {
					index_iterator it1=index_iterator::begin(kernel.properties, repfac.begin());
					it1+=asym_ranges[k][kk];
					for(unsigned int kkk=kk+1; kkk<asym_ranges[k].size(); ++kkk) {
						index_iterator it2=index_iterator::begin(kernel.properties, repfac.begin());
						it2+=asym_ranges[k][kkk];
						if(subtree_exact_equal(&kernel.properties, it1,it2)) {
							sym.set_multiplicity(i,0);
							goto traceterm;
							}
						}
					}
				}
			}

			{
			multiply(repfac.begin()->multiplier, sym.signature(i));
			multiply(repfac.begin()->multiplier, tab.projector_normalisation());
			iterator repfactop=repfac.begin();
			prod_unwrap_single_term(repfactop);
			rep.append_child(rep.begin(), repfac.begin());
			}

traceterm:
		;
		}
	it=tr.replace(it,rep.begin());

	sym.remove_multiplicity_zero();

	return result_t::l_applied;
	}