2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004 Ondra Kamenik
|
2023-12-05 15:44:23 +01:00
|
|
|
|
* Copyright © 2019-2023 Dynare Team
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
// Full symmetry tensor.
|
|
|
|
|
|
|
|
|
|
/* Here we define folded and unfolded tensors for full symmetry. All
|
|
|
|
|
tensors from here are identifying the multidimensional index with
|
|
|
|
|
columns. */
|
|
|
|
|
|
|
|
|
|
#ifndef FS_TENSOR_H
|
|
|
|
|
#define FS_TENSOR_H
|
|
|
|
|
|
2019-02-19 14:50:00 +01:00
|
|
|
|
#include "int_power.hh"
|
2023-11-29 19:00:21 +01:00
|
|
|
|
#include "symmetry.hh"
|
|
|
|
|
#include "tensor.hh"
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class FGSTensor;
|
|
|
|
|
class UGSTensor;
|
|
|
|
|
class FRSingleTensor;
|
|
|
|
|
class FSSparseTensor;
|
|
|
|
|
|
|
|
|
|
/* Folded tensor with full symmetry maintains only information about
|
2019-03-27 19:22:35 +01:00
|
|
|
|
number of symmetrical variables nv. Further, we implement what is
|
|
|
|
|
left from the super class FTensor.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
We implement getOffset() which should be used with care since
|
2019-01-08 16:09:25 +01:00
|
|
|
|
its complexity.
|
|
|
|
|
|
|
|
|
|
We implement a method adding a given general symmetry tensor to the
|
|
|
|
|
full symmetry tensor supposing the variables of the general symmetry
|
|
|
|
|
tensor are stacked giving only one variable of the full symmetry
|
2019-03-29 18:46:52 +01:00
|
|
|
|
tensor. ⎛y⎞
|
|
|
|
|
For instance, if x= ⎝u⎠, then we can add tensor [g_y²u] to tensor [g_x³].
|
|
|
|
|
This is done in method addSubTensor(). Consult FGSTensor class declaration
|
|
|
|
|
to know what is general symmetry tensor.
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
2019-03-27 19:22:35 +01:00
|
|
|
|
Note that the past-the-end index is of the form (nv,…,nv), because
|
2019-02-27 19:07:01 +01:00
|
|
|
|
of the specific implementation of FFSTensor::increment().
|
|
|
|
|
*/
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class UFSTensor;
|
|
|
|
|
class FFSTensor : public FTensor
|
|
|
|
|
{
|
|
|
|
|
int nv;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2019-02-27 19:07:01 +01:00
|
|
|
|
/* Constructs given the number of rows (explicit since the tensor is
|
|
|
|
|
column-oriented), the number of variables in each dimension, and the
|
|
|
|
|
number of dimensions */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FFSTensor(int r, int nvar, int d) :
|
|
|
|
|
FTensor(indor::along_col, IntSequence(d, nvar), r, calcMaxOffset(nvar, d), d), nv(nvar)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
|
|
|
|
/* Constructs a tensor by one-dimensional contraction from the higher
|
2019-03-27 19:22:35 +01:00
|
|
|
|
dimensional tensor t. This is, it constructs a tensor
|
|
|
|
|
|
|
|
|
|
[g_yⁿ]_α₁…αₙ = [t_yⁿ⁺¹]_α₁…αₙβ [x]^β
|
|
|
|
|
|
|
|
|
|
See the implementation for details. */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FFSTensor(const FFSTensor& t, const ConstVector& x);
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
|
|
|
|
/* Converts from sparse tensor (which is fully symmetric and folded by
|
|
|
|
|
nature). */
|
2023-11-29 19:00:21 +01:00
|
|
|
|
explicit FFSTensor(const FSSparseTensor& t);
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FFSTensor(const FFSTensor&) = default;
|
|
|
|
|
FFSTensor(FFSTensor&&) = default;
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
|
|
|
|
// Constructs from unfolded fully symmetric
|
2023-11-29 19:00:21 +01:00
|
|
|
|
explicit FFSTensor(const UFSTensor& ut);
|
2019-02-27 19:07:01 +01:00
|
|
|
|
|
|
|
|
|
// Constructs a subtensor of selected rows
|
2023-11-29 19:00:21 +01:00
|
|
|
|
FFSTensor(int first_row, int num, FFSTensor& t) : FTensor(first_row, num, t), nv(t.nv)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void increment(IntSequence& v) const override;
|
|
|
|
|
void decrement(IntSequence& v) const override;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] std::unique_ptr<UTensor> unfold() const override;
|
|
|
|
|
[[nodiscard]] Symmetry
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getSym() const
|
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return Symmetry {dimen()};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int getOffset(const IntSequence& v) const override;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void addSubTensor(const FGSTensor& t);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
nvar() const
|
|
|
|
|
{
|
|
|
|
|
return nv;
|
|
|
|
|
}
|
|
|
|
|
static int calcMaxOffset(int nvar, int d);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Unfolded fully symmetric tensor is almost the same in structure as
|
2019-03-27 19:22:35 +01:00
|
|
|
|
FFSTensor, but the method unfoldData(). It takes columns which also
|
2019-01-08 16:09:25 +01:00
|
|
|
|
exist in folded version and copies them to all their symmetrical
|
|
|
|
|
locations. This is useful when constructing unfolded tensor from
|
|
|
|
|
folded one. */
|
|
|
|
|
|
|
|
|
|
class UFSTensor : public UTensor
|
|
|
|
|
{
|
|
|
|
|
int nv;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-11-29 19:00:21 +01:00
|
|
|
|
UFSTensor(int r, int nvar, int d) :
|
|
|
|
|
UTensor(indor::along_col, IntSequence(d, nvar), r, calcMaxOffset(nvar, d), d), nv(nvar)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
UFSTensor(const UFSTensor& t, const ConstVector& x);
|
|
|
|
|
UFSTensor(const UFSTensor&) = default;
|
|
|
|
|
UFSTensor(UFSTensor&&) = default;
|
|
|
|
|
explicit UFSTensor(const FFSTensor& ft);
|
|
|
|
|
UFSTensor(int first_row, int num, UFSTensor& t) : UTensor(first_row, num, t), nv(t.nv)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void increment(IntSequence& v) const override;
|
|
|
|
|
void decrement(IntSequence& v) const override;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] std::unique_ptr<FTensor> fold() const override;
|
|
|
|
|
[[nodiscard]] Symmetry
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getSym() const
|
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return Symmetry {dimen()};
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int getOffset(const IntSequence& v) const override;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void addSubTensor(const UGSTensor& t);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
nvar() const
|
|
|
|
|
{
|
|
|
|
|
return nv;
|
|
|
|
|
}
|
|
|
|
|
static int
|
|
|
|
|
calcMaxOffset(int nvar, int d)
|
|
|
|
|
{
|
|
|
|
|
return power(nvar, d);
|
|
|
|
|
}
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
private:
|
|
|
|
|
void unfoldData();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|