Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SparseContainer.cc
Go to the documentation of this file.
1 ///
2 /// @file SparseContainer.cc
3 /// @brief Sparse tensor data container
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include <numeric>
13 #include <functional>
14 
15 #include <boost/fusion/adapted/std_pair.hpp>
16 
18 #include "Hammer/Exceptions.hh"
19 #include "Hammer/Tools/Utils.hh"
20 #include "Hammer/Math/Utils.hh"
22 #include "Hammer/Tools/Logging.hh"
23 
24 using namespace std;
25 
26 namespace Hammer {
27 
28  namespace MultiDimensional {
29 
30  SparseContainer::SparseContainer(const IndexList& dimensions, const LabelsList& labels)
31  : _indexing{dimensions, labels} {
32  }
33 
35  }
36 
37  SparseContainer::SparseContainer(const Serial::FBSingleTensor* input) {
38  if(input != nullptr) {
39  auto serialvals = input->vals();
40  auto serialpos = input->pos();
41  auto serialdims = input->dims();
42  auto seriallabels = input->labels();
43  if(serialdims != nullptr && seriallabels != nullptr) {
44  vector<IndexLabel> tmplabels;
45  tmplabels.reserve(seriallabels->size());
46  vector<IndexType> tmpdims;
47  tmpdims.reserve(serialdims->size());
48  for (unsigned int i = 0; i < serialdims->size(); ++i) {
49  tmplabels.push_back(static_cast<IndexLabel>(seriallabels->Get(i)));
50  tmpdims.push_back(serialdims->Get(i));
51  }
52  _indexing = LabeledIndexing<AlignedIndexing>{tmpdims, tmplabels};
53  }
54  if(serialvals != nullptr && serialpos != nullptr) {
55  for (unsigned int i = 0; i < serialvals->size(); ++i) {
56  _data[_indexing.posToAlignedPos(serialpos->Get(i))] = complex<double>{serialvals->Get(i)->re(), serialvals->Get(i)->im()};
57  }
58  }
59  }
60  }
61 
63  ASSERT(_indexing.checkValidIndices(indices));
64  PositionType pos = _indexing.indicesToPos(indices);
65  return getOrDefault(_data, pos, ElementType{});
66  }
67 
68  SparseContainer::ElementType SparseContainer::value(IndexList::const_iterator first, IndexList::const_iterator last) const {
69  PositionType pos = _indexing.indicesToPos(first, last);
70  return getOrDefault(_data, pos, ElementType{});
71  }
72 
73 
74  void SparseContainer::setValue(const IndexList& indices, ElementType value) {
75  ASSERT(_indexing.checkValidIndices(indices));
76  PositionType pos = _indexing.indicesToPos(indices);
77  _data[pos] = value;
78  }
79 
80  void SparseContainer::setValue(IndexList::const_iterator first, IndexList::const_iterator last,
81  ElementType value) {
82  ASSERT(_indexing.checkValidIndices(first, last));
83  PositionType pos = _indexing.indicesToPos(first, last);
84  _data[pos] = value;
85  }
86 
87 
89  return _data.begin();
90  }
91 
93  return _data.begin();
94  }
95 
97  return _data.end();
98  }
99 
101  return _data.end();
102  }
103 
106  return _data.erase(first, last);
107  }
108 
110  return _data[pos];
111  }
112 
113  size_t SparseContainer::rank() const {
114  return _indexing.rank();
115  }
116 
118  return _indexing.dims();
119  }
120 
122  return _indexing.labels();
123  }
124 
125  size_t SparseContainer::numValues() const {
126  return _indexing.numValues();
127  }
128 
129  size_t SparseContainer::dataSize() const {
130  return _data.size() * (sizeof(complex<double>) + sizeof(PositionType));
131  }
132 
133  size_t SparseContainer::entrySize() const {
134  return (sizeof(complex<double>) + sizeof(PositionType));
135  }
136 
138  return _indexing.labelIndex(label);
139  }
140 
141 
143  const UniqueLabelsList& indices) const {
144  return _indexing.getSameLabelPairs(other.labels(), indices);
145  }
146 
148  return _indexing.getOppositeLabelPairs(_indexing.spinIndices());
149  }
150 
151  bool SparseContainer::isSameShape(const IContainer& other) const {
152  return _indexing.isSameLabelShape(other.labels(), other.dims());
153  }
154 
155  bool SparseContainer::canAddAt(const IContainer& subContainer, IndexLabel coord, IndexType position) const {
156  return _indexing.canAddAt(subContainer.labels(), subContainer.dims(), coord, position);
157  }
158 
160  ASSERT(_indexing.checkValidIndices(coords));
161  PositionType pos = _indexing.indicesToPos(coords);
162  return _data[pos];
163  }
164 
166  return value(coords);
167  }
168 
169 
170  SparseContainer::reference SparseContainer::element(IndexList::const_iterator start, IndexList::const_iterator end) {
171  ASSERT(_indexing.checkValidIndices(start, end));
172  PositionType pos = _indexing.indicesToPos(start, end);
173  return _data[pos];
174  }
175 
176  SparseContainer::ElementType SparseContainer::element(IndexList::const_iterator start, IndexList::const_iterator end) const {
177  return value(start, end);
178  }
179 
180  bool SparseContainer::compare(const IContainer& other) const {
181  const SparseContainer* tmp = dynamic_cast<const SparseContainer*>(&other);
182  if(tmp == nullptr) return false;
183  bool dimcheck = _indexing.isSameLabelShape(tmp->_indexing);
184  if(!dimcheck) return false;
185  if (_data.size() != tmp->_data.size())
186  return false;
187  return equal(
188  _data.begin(), _data.end(), tmp->_data.begin(),
189  [](const pair<PositionType, ElementType>& a, const pair<PositionType, ElementType>& b) -> bool {
190  return (a.first == b.first) && isZero(a.second - b.second);
191  });
192  }
193 
195  SparseContainer* t = new SparseContainer{*this};
196  return TensorData{static_cast<IContainer*>(t)};
197  }
198 
199 
201  return NonZeroIt{new ItAligned{_data.begin()}};
202  }
203 
205  return NonZeroIt{new ItAligned{_data.end()}};
206  }
207 
209  _data.clear();
210  }
211 
213  for(auto& elem: _data) {
214  elem.second *= value;
215  }
216  return static_cast<IContainer&>(*this);
217  }
218 
220  for (auto& elem : _data) {
221  elem.second *= value;
222  }
223  return static_cast<IContainer&>(*this);
224  }
225 
226 
228  for (auto& elem : _data) {
229  elem.second = conj(elem.second);
230  }
231  _indexing.flipLabels();
232  return *this;
233  }
234 
235  SparseContainer::SerialType SparseContainer::write(flatbuffers::FlatBufferBuilder* msgwriter) const {
236  vector<Serial::FBComplex> datalist;
237  vector<uint32_t> poslist;
238  datalist.reserve(_data.size());
239  poslist.reserve(_data.size());
240  if (_data.size() > 4294967295ul) {
241  MSG_ERROR("Error saving binary tensor: too many entries!");
242  }
243  // size_t count = 0ul;
244  // size_t count2 = 0ul;
245  for (auto& elem: _data) {
246  if (!isZero(elem.second)) {
247  // if (!isZero(_data[i].real())) count++;
248  // if (!isZero(_data[i].imag())) count++;
249  // count2++;
250  auto resc = Serial::FBComplex{elem.second.real(), elem.second.imag()};
251  datalist.push_back(resc);
252  poslist.push_back(static_cast<uint32_t>(_indexing.alignedPosToPos(elem.first)));
253  }
254  }
255  // std::cout << numValues() << ": " << 1.-(count*(8+4) + 4*4)/(16.*numValues()+4)
256  // << " vs " << 1.-(count2*(16+4)+4*2)/(16.*numValues()+4) << std::endl;
257  auto serialdata = msgwriter->CreateVectorOfStructs(datalist.data(), datalist.size());
258  auto serialpos = msgwriter->CreateVector(poslist);
259  vector<uint16_t> dims;
260  for (auto elem : _indexing.dims()) {
261  dims.push_back(static_cast<uint16_t>(elem));
262  }
263  vector<int16_t> labels;
264  for (auto elem : _indexing.labels()) {
265  labels.push_back(static_cast<int16_t>(elem));
266  }
267  auto serialdims = msgwriter->CreateVector(dims);
268  auto seriallabels = msgwriter->CreateVector(labels);
269  Serial::FBSingleTensorBuilder serialtensor{*msgwriter};
270  serialtensor.add_sparse(true);
271  serialtensor.add_vals(serialdata);
272  serialtensor.add_pos(serialpos);
273  serialtensor.add_labels(seriallabels);
274  serialtensor.add_dims(serialdims);
275  auto out = serialtensor.Finish();
276  return make_pair(out.Union(), Serial::FBTensorTypes::FBSingleTensor);
277  }
278 
280  return Log::getLog("Hammer.SparseContainer");
281  }
282 
284  return _indexing;
285  }
286 
287  TensorData makeEmptySparse(const IndexList& dimensions, const LabelsList& labels) {
288  auto result = new SparseContainer{dimensions, labels};
289  return TensorData{static_cast<IContainer*>(result)};
290  }
291 
293  auto result = new SparseContainer{indexing};
294  return TensorData{static_cast<IContainer*>(result)};
295  }
296 
297  SparseContainer::ItAligned::ItAligned(DataType::const_iterator it) : _it{it} { }
298 
300  return _it->second;
301  }
302 
304  return _it->first;
305  }
306 
308  advance(_it, n);
309  }
310 
311  bool SparseContainer::ItAligned::isSame(const ItBase& other) const {
312  return _it == static_cast<const ItAligned&>(other)._it;
313  }
314 
316  return true;
317  }
318 
319  ptrdiff_t SparseContainer::ItAligned::distanceFrom(const ItBase& other) const {
320  return distance(static_cast<const ItAligned&>(other)._it, _it);
321  }
322 
323  } // namespace MultiDimensional
324 
325 } // namespace Hammer
Log & getLog() const
logging facility
TensorData makeEmptySparse(const IndexList &dimensions, const LabelsList &labels)
std::pair< flatbuffers::Offset< void >, Serial::FBTensorTypes > SerialType
Definition: IContainer.hh:68
bool compare(const IContainer &other) const override
const LabeledIndexing< AlignedIndexing > & getIndexing() const
SerialType write(flatbuffers::FlatBufferBuilder *msgwriter) const override
virtual LabelsList labels() const =0
std::vector< IndexPair > IndexPairList
size_t PositionType
#define ASSERT(x)
Definition: Exceptions.hh:95
Message logging routines.
std::complex< double > ElementType
Definition: IContainer.hh:34
uint16_t IndexType
IndexPairList getSameLabelPairs(const IContainer &other, const UniqueLabelsList &indices) const override
std::unique_ptr< IContainer > TensorData
IContainer::ElementType value() const override
static Log & getLog(const std::string &name)
Get a logger with the given name.
Definition: Logging.cc:139
LabeledIndexing< AlignedIndexing > _indexing
ValueType getOrDefault(const std::map< KeyType, ValueType > &data, KeyType key, ValueType fallback)
Definition: Tools/Utils.hh:39
Hammer exception definitions.
Sparse tensor data container.
std::vector< IndexType > IndexList
ElementType value(const IndexList &indices) const
Logging class.
Definition: Logging.hh:33
bool canAddAt(const IContainer &subContainer, IndexLabel coord, IndexType position) const override
IndexLabel
label identifiers of tensor indices they are used to determine which indices can be contracted togeth...
Definition: IndexLabels.hh:27
virtual IndexList dims() const =0
bool isZero(const std::complex< double > val)
Definition: Math/Utils.hh:25
ptrdiff_t distanceFrom(const ItBase &other) const override
std::vector< IndexLabel > LabelsList
std::set< IndexLabel > UniqueLabelsList
iterator erase(const_iterator first, const_iterator last)
bool isSame(const ItBase &other) const override
#define MSG_ERROR(x)
Definition: Logging.hh:367
IndexType labelToIndex(IndexLabel label) const override
void setValue(const IndexList &indices, ElementType value=0.)
auto end(reversion_wrapper< T > w)
Definition: Tools/Utils.hh:84
Serialization related typedefs and includes.
IndexPairList getSpinLabelPairs() const override
IContainer & operator*=(double value) override
reference operator[](PositionType pos)
bool isSameShape(const IContainer &other) const override
SparseContainer(const IndexList &dimensions, const LabelsList &labels)
reference element(const IndexList &coords={}) override