2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004 Ondra Kamenik
|
|
|
|
|
* Copyright © 2019 Dynare Team
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Dynare.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
// Row-wise full symmetry tensor.
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* Here we define classes for full symmetry tensors with the multidimensional
|
|
|
|
|
index identified with rows. The primary usage is for storage of data coming
|
|
|
|
|
from (or from a sum of)
|
|
|
|
|
ₗ
|
2019-05-06 18:43:54 +02:00
|
|
|
|
∏ [g_{s^|cₘ|}]_cₘ(α)^γₘ
|
2019-04-16 15:04:19 +02:00
|
|
|
|
ᵐ⁼¹
|
|
|
|
|
where α comes from a multidimensional index that goes through some set S,
|
|
|
|
|
and cₘ is some equivalence class. So we model a tensor of the form:
|
|
|
|
|
|
|
|
|
|
⎡ ₗ ⎤
|
2019-05-06 18:43:54 +02:00
|
|
|
|
⎢ ∏ [g_{s^|cₘ|}]_cₘ(α)^γₘ⎥
|
2019-04-16 15:04:19 +02:00
|
|
|
|
⎣ᵐ⁼¹ ⎦S^γ₁…γₗ
|
|
|
|
|
|
|
|
|
|
Since all γ₁…γₗ correspond to the same variable, the tensor is fully
|
|
|
|
|
symmetric. The set of indices S cannot be very large and sometimes it is
|
|
|
|
|
only one element. This case is handled in a special subclass.
|
|
|
|
|
|
|
|
|
|
We provide both folded and unfolded versions. Their logic is perfectly the
|
|
|
|
|
same as in UFSTensor and FFSTensor with two exceptions. One has been already
|
|
|
|
|
mentioned, the multidimensional index is along the rows. The second are
|
|
|
|
|
conversions between the two types. Since this kind of tensor is used to
|
|
|
|
|
multiply (from the right) a tensor whose multidimensional index is
|
|
|
|
|
identified with columns, we will need a different way of a conversion. If
|
|
|
|
|
the multiplication of two folded tensors is to be equivalent with
|
|
|
|
|
multiplication of two unfolded, the folding of the right tensor must sum all
|
|
|
|
|
equivalent elements since they are multiplied with the same number from the
|
|
|
|
|
folded tensor. (Equivalent here means all elements of unfolded tensor
|
2019-01-08 16:09:25 +01:00
|
|
|
|
corresponding to one element in folded tensor.) For this reason, it is
|
|
|
|
|
necessary to calculate a column number from the given sequence, so we
|
2019-04-16 15:04:19 +02:00
|
|
|
|
implement getOffset(). Process of unfolding is not used, so we implemented
|
|
|
|
|
it so that unfolding and then folding a tensor would yield the same data. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
#ifndef RFS_TENSOR_H
|
|
|
|
|
#define RFS_TENSOR_H
|
|
|
|
|
|
|
|
|
|
#include "tensor.hh"
|
|
|
|
|
#include "fs_tensor.hh"
|
|
|
|
|
#include "symmetry.hh"
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This is straightforward and very similar to UFSTensor. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class FRTensor;
|
|
|
|
|
class URTensor : public UTensor
|
|
|
|
|
{
|
|
|
|
|
int nv;
|
|
|
|
|
public:
|
|
|
|
|
URTensor(int c, int nvar, int d)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
: UTensor(indor::along_row, IntSequence(d, nvar),
|
2019-01-08 16:09:25 +01:00
|
|
|
|
UFSTensor::calcMaxOffset(nvar, d), c, d), nv(nvar)
|
|
|
|
|
{
|
|
|
|
|
}
|
2019-02-20 14:36:35 +01:00
|
|
|
|
URTensor(const URTensor &) = default;
|
|
|
|
|
URTensor(URTensor &&) = default;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
explicit URTensor(const FRTensor &ft);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-02-20 14:36:35 +01:00
|
|
|
|
~URTensor() override = default;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-01-09 16:26:42 +01:00
|
|
|
|
void increment(IntSequence &v) const override;
|
|
|
|
|
void decrement(IntSequence &v) const override;
|
2019-02-20 14:25:32 +01:00
|
|
|
|
std::unique_ptr<FTensor> fold() const override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-01-09 16:26:42 +01:00
|
|
|
|
int getOffset(const IntSequence &v) const override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
int
|
|
|
|
|
nvar() const
|
|
|
|
|
{
|
|
|
|
|
return nv;
|
|
|
|
|
}
|
|
|
|
|
Symmetry
|
|
|
|
|
getSym() const
|
|
|
|
|
{
|
2019-02-08 18:38:05 +01:00
|
|
|
|
return Symmetry{dimen()};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This is straightforward and very similar to FFSTensor. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class FRTensor : public FTensor
|
|
|
|
|
{
|
|
|
|
|
int nv;
|
|
|
|
|
public:
|
|
|
|
|
FRTensor(int c, int nvar, int d)
|
2019-02-12 17:30:10 +01:00
|
|
|
|
: FTensor(indor::along_row, IntSequence(d, nvar),
|
2019-01-08 16:09:25 +01:00
|
|
|
|
FFSTensor::calcMaxOffset(nvar, d), c, d), nv(nvar)
|
|
|
|
|
{
|
|
|
|
|
}
|
2019-02-20 14:36:35 +01:00
|
|
|
|
FRTensor(const FRTensor &) = default;
|
|
|
|
|
FRTensor(FRTensor &&) = default;
|
2019-02-26 18:57:36 +01:00
|
|
|
|
explicit FRTensor(const URTensor &ut);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-02-20 14:36:35 +01:00
|
|
|
|
~FRTensor() override = default;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-01-09 16:26:42 +01:00
|
|
|
|
void increment(IntSequence &v) const override;
|
|
|
|
|
void decrement(IntSequence &v) const override;
|
2019-02-20 14:25:32 +01:00
|
|
|
|
std::unique_ptr<UTensor> unfold() const override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nvar() const
|
|
|
|
|
{
|
|
|
|
|
return nv;
|
|
|
|
|
}
|
|
|
|
|
int
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getOffset(const IntSequence &v) const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return FTensor::getOffset(v, nv);
|
|
|
|
|
}
|
|
|
|
|
Symmetry
|
|
|
|
|
getSym() const
|
|
|
|
|
{
|
2019-02-08 18:38:05 +01:00
|
|
|
|
return Symmetry{dimen()};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* The following class represents specialization of URTensor coming from
|
|
|
|
|
Kronecker multiplication of a few vectors. So the resulting row-oriented
|
|
|
|
|
tensor has one column. We provide two constructors, one constructs the
|
|
|
|
|
tensor from a few vectors stored as std::vector<ConstVector>. The second
|
|
|
|
|
makes the Kronecker power of one given vector. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class URSingleTensor : public URTensor
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
URSingleTensor(int nvar, int d)
|
|
|
|
|
: URTensor(1, nvar, d)
|
|
|
|
|
{
|
|
|
|
|
}
|
2019-02-06 15:50:01 +01:00
|
|
|
|
URSingleTensor(const std::vector<ConstVector> &cols);
|
2019-01-08 16:09:25 +01:00
|
|
|
|
URSingleTensor(const ConstVector &v, int d);
|
2019-02-20 14:36:35 +01:00
|
|
|
|
URSingleTensor(const URSingleTensor &) = default;
|
|
|
|
|
URSingleTensor(URSingleTensor &&) = default;
|
|
|
|
|
~URSingleTensor() override = default;
|
2019-02-20 14:25:32 +01:00
|
|
|
|
std::unique_ptr<FTensor> fold() const override;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This class represents one column row-oriented tensor. The only way to
|
|
|
|
|
construct it is from URSingleTensor or from scratch. The folding algorithm
|
|
|
|
|
is the same as folding of general URTensor. Only its implementation is
|
|
|
|
|
different, since we do not copy rows, but only elements. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class FRSingleTensor : public FRTensor
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FRSingleTensor(int nvar, int d)
|
|
|
|
|
: FRTensor(1, nvar, d)
|
|
|
|
|
{
|
|
|
|
|
}
|
2019-02-27 19:07:01 +01:00
|
|
|
|
explicit FRSingleTensor(const URSingleTensor &ut);
|
2019-02-20 14:36:35 +01:00
|
|
|
|
FRSingleTensor(const FRSingleTensor &) = default;
|
|
|
|
|
FRSingleTensor(FRSingleTensor &&) = default;
|
|
|
|
|
~FRSingleTensor() override = default;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|