2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004 Ondra Kamenik
|
2023-12-04 17:55:59 +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
|
|
|
|
|
|
|
|
|
// Sparse tensor.
|
|
|
|
|
|
|
|
|
|
/* Here we declare a sparse full and general symmetry tensors with the
|
2019-04-16 15:04:19 +02:00
|
|
|
|
multidimensional index along columns. We implement them as a std::multimap
|
|
|
|
|
associating to each sequence of coordinates IntSequence a set of pairs (row,
|
|
|
|
|
number). This is very convenient but not optimal in terms of memory
|
|
|
|
|
consumption. So the implementation can be changed.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
The current std::multimap implementation allows insertions. Another
|
2019-01-08 16:09:25 +01:00
|
|
|
|
advantage of this approach is that we do not need to calculate column
|
2019-04-16 15:04:19 +02:00
|
|
|
|
numbers from the IntSequence, since the column is accessed directly via the
|
|
|
|
|
key which is IntSequence.
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
The only operation we need to do with the full symmetry sparse tensor
|
|
|
|
|
is a left multiplication of a row oriented single column tensor. The
|
2019-04-16 15:04:19 +02:00
|
|
|
|
result of such an operation is a column of the same size as the sparse
|
2019-01-08 16:09:25 +01:00
|
|
|
|
tensor. Other important operations are slicing operations. We need to
|
|
|
|
|
do sparse and dense slices of full symmetry sparse tensors. In fact,
|
|
|
|
|
the only constructor of general symmetry sparse tensor is slicing from
|
|
|
|
|
the full symmetry sparse. */
|
|
|
|
|
|
|
|
|
|
#ifndef SPARSE_TENSOR_H
|
|
|
|
|
#define SPARSE_TENSOR_H
|
|
|
|
|
|
2023-11-29 19:00:21 +01:00
|
|
|
|
#include "Vector.hh"
|
|
|
|
|
#include "gs_tensor.hh"
|
2019-01-08 16:09:25 +01:00
|
|
|
|
#include "symmetry.hh"
|
|
|
|
|
#include "tensor.hh"
|
|
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
|
|
struct ltseq
|
|
|
|
|
{
|
|
|
|
|
bool
|
2023-11-29 19:00:21 +01:00
|
|
|
|
operator()(const IntSequence& s1, const IntSequence& s2) const
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return s1 < s2;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This is a super class of both full symmetry and general symmetry sparse
|
|
|
|
|
tensors. It contains a std::multimap and implements insertions. It tracks
|
|
|
|
|
maximum and minimum row, for which there is an item. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class SparseTensor
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-02-27 19:07:01 +01:00
|
|
|
|
using Map = std::multimap<IntSequence, std::pair<int, double>, ltseq>;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
protected:
|
|
|
|
|
Map m;
|
2019-02-22 17:44:07 +01:00
|
|
|
|
int dim;
|
|
|
|
|
int nr;
|
|
|
|
|
int nc;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
int first_nz_row;
|
2023-12-06 16:31:03 +01:00
|
|
|
|
int last_nz_row {-1};
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
2023-12-06 16:31:03 +01:00
|
|
|
|
SparseTensor(int d, int nnr, int nnc) : dim(d), nr(nnr), nc(nnc), first_nz_row(nr)
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
2023-12-04 17:55:59 +01:00
|
|
|
|
virtual ~SparseTensor() = default;
|
2019-02-27 19:07:01 +01:00
|
|
|
|
void insert(IntSequence s, int r, double c);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const Map&
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getMap() const
|
|
|
|
|
{
|
|
|
|
|
return m;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
dimen() const
|
|
|
|
|
{
|
|
|
|
|
return dim;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
nrows() const
|
|
|
|
|
{
|
|
|
|
|
return nr;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
ncols() const
|
|
|
|
|
{
|
|
|
|
|
return nc;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getFillFactor() const
|
|
|
|
|
{
|
2023-11-29 19:00:21 +01:00
|
|
|
|
return static_cast<double>(m.size()) / nrows() / ncols();
|
2019-01-08 16:09:25 +01:00
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] double getFoldIndexFillFactor() const;
|
|
|
|
|
[[nodiscard]] double getUnfoldIndexFillFactor() const;
|
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getNumNonZero() const
|
|
|
|
|
{
|
|
|
|
|
return m.size();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getFirstNonZeroRow() const
|
|
|
|
|
{
|
|
|
|
|
return first_nz_row;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getLastNonZeroRow() const
|
|
|
|
|
{
|
|
|
|
|
return last_nz_row;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] virtual const Symmetry& getSym() const = 0;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
void print() const;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] bool isFinite() const;
|
2019-01-08 16:09:25 +01:00
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This is a full symmetry sparse tensor. It implements multColumnAndAdd() and,
|
|
|
|
|
in addition to SparseTensor, it has ‘nv’ (number of variables) and symmetry
|
|
|
|
|
(basically it is a dimension). */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class FSSparseTensor : public SparseTensor
|
|
|
|
|
{
|
|
|
|
|
private:
|
2019-02-22 17:44:07 +01:00
|
|
|
|
int nv;
|
|
|
|
|
Symmetry sym;
|
2023-11-29 19:00:21 +01:00
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
public:
|
|
|
|
|
FSSparseTensor(int d, int nvar, int r);
|
2019-02-27 19:07:01 +01:00
|
|
|
|
void insert(IntSequence s, int r, double c);
|
2023-11-29 19:00:21 +01:00
|
|
|
|
void multColumnAndAdd(const Tensor& t, Vector& v) const;
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const Symmetry&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getSym() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return sym;
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] int
|
2019-01-08 16:09:25 +01:00
|
|
|
|
nvar() const
|
|
|
|
|
{
|
|
|
|
|
return nv;
|
|
|
|
|
}
|
|
|
|
|
void print() const;
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-16 15:04:19 +02:00
|
|
|
|
/* This is a general symmetry sparse tensor. It has TensorDimens and can be
|
|
|
|
|
constructed as a slice of the full symmetry sparse tensor. The slicing
|
|
|
|
|
constructor takes the same form as the slicing FGSTensor constructor from
|
|
|
|
|
full symmetry sparse tensor. */
|
2019-01-08 16:09:25 +01:00
|
|
|
|
|
|
|
|
|
class GSSparseTensor : public SparseTensor
|
|
|
|
|
{
|
|
|
|
|
private:
|
2019-02-22 17:44:07 +01:00
|
|
|
|
TensorDimens tdims;
|
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
|
|
|
|
GSSparseTensor(const FSSparseTensor& t, const IntSequence& ss, const IntSequence& coor,
|
|
|
|
|
TensorDimens td);
|
2019-02-27 19:07:01 +01:00
|
|
|
|
void insert(IntSequence s, int r, double c);
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const Symmetry&
|
2019-01-09 16:26:42 +01:00
|
|
|
|
getSym() const override
|
2019-01-08 16:09:25 +01:00
|
|
|
|
{
|
|
|
|
|
return tdims.getSym();
|
|
|
|
|
}
|
2023-12-05 15:44:23 +01:00
|
|
|
|
[[nodiscard]] const TensorDimens&
|
2019-01-08 16:09:25 +01:00
|
|
|
|
getDims() const
|
|
|
|
|
{
|
|
|
|
|
return tdims;
|
|
|
|
|
}
|
|
|
|
|
void print() const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|