File: gs_tensor.hweb

package info (click to toggle)
dynare 4.5.7-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 49,408 kB
  • sloc: cpp: 84,998; ansic: 29,058; pascal: 13,843; sh: 4,833; objc: 4,236; yacc: 3,622; makefile: 2,278; lex: 1,541; python: 236; lisp: 69; xml: 8
file content (222 lines) | stat: -rw-r--r-- 8,016 bytes parent folder | download | duplicates (5)
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
@q $Id: gs_tensor.hweb 741 2006-05-09 11:12:46Z kamenik $ @>
@q Copyright 2004, Ondra Kamenik @>

@*2 General symmetry tensor. Start of {\tt gs\_tensor.h} file.

Here we define tensors for general symmetry. All tensors from here are
identifying the multidimensional index with columns. Thus all
symmetries regard to columns. The general symmetry here is not the most
general. It captures all symmetries of indices which are given by
continuous partitioning of indices. Two items are symmetric if they
belong to the same group. The continuity implies that if two items
belong to one group, then all items between them belong to that
group. This continuous partitioning of indices is described by
|Symmetry| class.

The dimension of the tensors here are described (besides the symmetry)
also by number of variables for each group. This is dealt in the class
for tensor dimensions defined also here.

@c
#ifndef GS_TENSOR_H
#define GS_TENSOR_H

#include "tensor.h"
#include "fs_tensor.h"
#include "symmetry.h"
#include "rfs_tensor.h"

class FGSTensor;
class UGSTensor;
class FSSparseTensor;

@<|TensorDimens| class declaration@>;
@<|FGSTensor| class declaration@>;
@<|UGSTensor| class declaration@>;

#endif

@ This class encapsulates symmetry information for the general
symmetry tensor. It maintains a vector of variable numbers |nvs|, and
symmetry |sym|. For example, let the symmetry be $y^2u^3$, and
variable numbers be 10 for $y$, and 5 for $u$. Then the |nvs| is
$(10,5)$, and |sym| is $(2,3)$. Also it maintains |nvmax| unfolded |nvs| with
respect to the symmetry, this is $(10,10,5,5,5)$.

The constructors of |TensorDimens| are clear and pretty intuitive but
the constructor which is used for slicing fully symmetric tensor. It
constructs the dimensions from the partitioning of variables of fully
symmetric tensor. Let the partitioning be, for instance, $(a,b,c,d)$,
where $(n_a,n_b,n_c,n_d)$ are lengths of the partitions. Let one want
to get a slice only of the part of the fully symmetric tensor
corresponding to indices of the form $b^2d^3$. This corresponds to the
symmetry $a^0b^2c^0d^3$. So, the dimension of the slice would be also
$(n_a,n_b,n_c,n_d)$ for number of variables and $(0,2,0,3)$ for the
symmetry. So we provide the constructor which takes sizes of
partitions $(n_a,n_b,n_c,n_d)$ as |IntSequence|, and indices of picked
partitions, in our case $(1,1,3,3,3)$, as |IntSequence|.

The class is able to calculate number of offsets (columns or rows depending
what matrix coordinate we describe) in unfolded and folded tensors
with the given symmetry.

@s TensorDimens int

@<|TensorDimens| class declaration@>=
class TensorDimens {
protected:@;
	IntSequence nvs;
	Symmetry sym;
	IntSequence nvmax;
public:@;
	TensorDimens(const Symmetry& s, const IntSequence& nvars)
		: nvs(nvars), sym(s), nvmax(sym, nvs)@+ {}
	TensorDimens(int nvar, int dimen)
		: nvs(1), sym(dimen), nvmax(dimen, nvar)
		{@+ nvs[0] = nvar;@+}
	TensorDimens(const TensorDimens& td)
		: nvs(td.nvs), sym(td.sym), nvmax(td.nvmax)@+ {}
	virtual ~TensorDimens()@+ {}
	TensorDimens(const IntSequence& ss, const IntSequence& coor);
	const TensorDimens& operator=(const TensorDimens& td)
		{@+ nvs = td.nvs;@+ sym = td.sym;@+ nvmax = td.nvmax;@+ return *this;@+}
	bool operator==(const TensorDimens& td) const
		{@+ return nvs == td.nvs && sym == td.sym;@+}
	bool operator!=(const TensorDimens& td) const
		{@+ return !operator==(td);@+}

	int dimen() const
		{@+ return sym.dimen();@+}
	int getNVX(int i) const
		{@+ return nvmax[i];@+}
	const IntSequence& getNVS() const
		{ @+ return nvs;@+}
	const IntSequence& getNVX() const
		{@+ return nvmax;@+}
	const Symmetry& getSym() const
		{@+ return sym;@+}

	int calcUnfoldMaxOffset() const;
	int calcFoldMaxOffset() const;
	int calcFoldOffset(const IntSequence& v) const;
	void decrement(IntSequence& v) const; 
};

@ Here is a class for folded general symmetry tensor. It only contains
tensor dimensions, it defines types for indices, implement virtual
methods of super class |FTensor|.

We add a method |contractAndAdd| which performs a contraction of one
variable in the tensor. This is, for instance
$$\left[r_{x^iz^k}\right]_{\alpha_1\ldots\alpha_i\gamma_1\ldots\gamma_k}=
\left[t_{x^iy^jz^k}\right]_{\alpha_1\ldots\alpha_i\beta_1\ldots\beta_j\gamma_1\ldots\gamma_k}
\left[c\right]^{\beta_1\ldots\beta_j}
$$

Also we add |getOffset| which should be used with care.

@<|FGSTensor| class declaration@>=
class GSSparseTensor;
class FGSTensor : public FTensor {
	friend class UGSTensor;

	const TensorDimens tdims;
public:@;
	@<|FGSTensor| constructor declarations@>;
	virtual ~FGSTensor()@+ {}

	void increment(IntSequence& v) const;
	void decrement(IntSequence& v) const
		{@+ tdims.decrement(v);@+}
	UTensor& unfold() const;
	const TensorDimens& getDims() const
		{@+ return tdims;@+}
	const Symmetry& getSym() const
		{@+ return getDims().getSym();@+}

	void contractAndAdd(int i, FGSTensor& out,
						const FRSingleTensor& col) const;
	int getOffset(const IntSequence& v) const
		{@+ return tdims.calcFoldOffset(v);@+}
};

@ These are standard constructors followed by two slicing. The first
constructs a slice from the sparse, the second from the dense (both
fully symmetric). Next constructor is just a conversion from
|GSSParseTensor|. The last constructor allows for in-place conversion
from |FFSTensor| to |FGSTensor|.

@<|FGSTensor| constructor declarations@>=
	FGSTensor(int r, const TensorDimens& td)
		: FTensor(along_col, td.getNVX(), r,
				  td.calcFoldMaxOffset(), td.dimen()), tdims(td)@+ {}
	FGSTensor(const FGSTensor& ft)
		: FTensor(ft), tdims(ft.tdims)@+ {}
	FGSTensor(const UGSTensor& ut);
	FGSTensor(int first_row, int num, FGSTensor& t)
		: FTensor(first_row, num, t), tdims(t.tdims)@+ {}
	FGSTensor(const FSSparseTensor& t, const IntSequence& ss,
			  const IntSequence& coor, const TensorDimens& td);
	FGSTensor(const FFSTensor& t, const IntSequence& ss,
			  const IntSequence& coor, const TensorDimens& td);
	FGSTensor(const GSSparseTensor& sp);
	FGSTensor(FFSTensor& t)
		: FTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())@+ {}


@ Besides similar things that has |FGSTensor|, we have here also
method |unfoldData|, and helper method |getFirstIndexOf|
which corresponds to sorting coordinates in fully symmetric case (here
the action is more complicated, so we put it to the method).

@<|UGSTensor| class declaration@>=
class UGSTensor : public UTensor {
	friend class FGSTensor;

	const TensorDimens tdims;
public:@;
	@<|UGSTensor| constructor declarations@>;
	virtual ~UGSTensor()@+ {}

	void increment(IntSequence& v) const;
	void decrement(IntSequence& v) const;
	FTensor& fold() const;
	const TensorDimens& getDims() const
		{@+ return tdims;@+}
	const Symmetry& getSym() const
		{@+ return getDims().getSym();@+}

	void contractAndAdd(int i, UGSTensor& out,
						const URSingleTensor& col) const;
	int getOffset(const IntSequence& v) const;
private:@;
	void unfoldData();
public:@;
	index getFirstIndexOf(const index& in) const;
};


@ These are standard constructors. The last two constructors are
slicing. The first makes a slice from fully symmetric sparse, the
second from fully symmetric dense unfolded tensor. The last
constructor allows for in-place conversion from |UFSTensor| to
|UGSTensor|.

@<|UGSTensor| constructor declarations@>=
	UGSTensor(int r, const TensorDimens& td)
		: UTensor(along_col, td.getNVX(), r,
				  td.calcUnfoldMaxOffset(), td.dimen()), tdims(td)@+ {}
	UGSTensor(const UGSTensor& ut)
		: UTensor(ut), tdims(ut.tdims)@+ {}
	UGSTensor(const FGSTensor& ft);
	UGSTensor(int first_row, int num, UGSTensor& t)
		: UTensor(first_row,  num, t), tdims(t.tdims)@+ {}
	UGSTensor(const FSSparseTensor& t, const IntSequence& ss,
			  const IntSequence& coor, const TensorDimens& td);
	UGSTensor(const UFSTensor& t, const IntSequence& ss,
			  const IntSequence& coor, const TensorDimens& td);
	UGSTensor(UFSTensor& t)
		: UTensor(0, t.nrows(), t), tdims(t.nvar(), t.dimen())@+ {}


@ End of {\tt gs\_tensor.h} file.