xerus
a general purpose tensor library
measurments.cpp
Go to the documentation of this file.
1 // Xerus - A General Purpose Tensor Library
2 // Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf.
3 //
4 // Xerus is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as published
6 // by the Free Software Foundation, either version 3 of the License,
7 // or (at your option) any later version.
8 //
9 // Xerus is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
13 //
14 // You should have received a copy of the GNU Affero General Public License
15 // along with Xerus. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // For further information on Xerus visit https://libXerus.org
18 // or contact us at contact@libXerus.org.
19 
25 #include <xerus/misc/check.h>
26 #include <xerus/measurments.h>
27 
28 #include <xerus/misc/sort.h>
29 #include <xerus/misc/random.h>
30 
31 #include <xerus/index.h>
32 #include <xerus/tensor.h>
33 #include <xerus/tensorNetwork.h>
34 #include <xerus/ttNetwork.h>
35 #include <xerus/indexedTensor.h>
36 #include <xerus/misc/internal.h>
37 
38 
39 namespace xerus {
40  // --------------------- SinglePointMeasurementSet -----------------
41 
42  SinglePointMeasurementSet SinglePointMeasurementSet::random(const size_t _numMeasurements, const std::vector<size_t>& _dimensions) {
44  result.create_random_positions(_numMeasurements, _dimensions);
45  result.measuredValues.resize(_numMeasurements, 0);
46  return result;
47  }
48 
49 
50  SinglePointMeasurementSet SinglePointMeasurementSet::random(const size_t _numMeasurements, const Tensor& _solution) {
52  result.create_random_positions(_numMeasurements, _solution.dimensions);
53  result.measure(_solution);
54  return result;
55  }
56 
57  SinglePointMeasurementSet SinglePointMeasurementSet::random(const size_t _numMeasurements, const TensorNetwork& _solution) {
59  result.create_random_positions(_numMeasurements, _solution.dimensions);
60  result.measure(_solution);
61  return result;
62  }
63 
64  SinglePointMeasurementSet SinglePointMeasurementSet::random(const size_t _numMeasurements, const std::vector<size_t>& _dimensions, std::function<value_t(const std::vector<size_t>&)> _callback) {
66  result.create_random_positions(_numMeasurements, _dimensions);
67  result.measure(_callback);
68  return result;
69  }
70 
71 
73  REQUIRE(positions.size() == measuredValues.size(), "Inconsitend SinglePointMeasurementSet encountered.");
74  return positions.size();
75  }
76 
77 
79  return positions.empty() ? 0 : positions[0].size();
80  }
81 
82 
83  void SinglePointMeasurementSet::add(std::vector<size_t> _position, const value_t _measuredValue) {
84  REQUIRE(positions.empty() || _position.size() == positions.back().size(), "Given _position has incorrect degree " << _position.size() << ". Expected " << positions.back().size() << ".");
85  positions.emplace_back(_position);
86  measuredValues.emplace_back(_measuredValue);
87  }
88 
89  void SinglePointMeasurementSet::sort(const bool _positionsOnly) {
90  const auto comperator = [](const std::vector<size_t>& _lhs, const std::vector<size_t>& _rhs) {
91  REQUIRE(_lhs.size() == _rhs.size(), "Inconsistent degrees in measurment positions.");
92  for (size_t i = 0; i < _lhs.size(); ++i) {
93  if (_lhs[i] < _rhs[i]) { return true; }
94  if (_lhs[i] > _rhs[i]) { return false; }
95  }
96  return false; // equality
97  };
98 
99  if(_positionsOnly) {
100  std::sort(positions.begin(), positions.end(), comperator);
101  } else {
102  REQUIRE(positions.size() == measuredValues.size(), "Inconsitend SinglePointMeasurementSet encountered.");
104  }
105  }
106 
107 
109  const auto cSize = size();
110  double norm = 0.0;
111  for(size_t i = 0; i < cSize; ++i) {
112  norm += misc::sqr(measuredValues[i]);
113  }
114  return std::sqrt(norm);
115  }
116 
117 
119  const auto cSize = size();
120  for(size_t i = 0; i < cSize; ++i) {
121  measuredValues[i] = _solution[positions[i]];
122  }
123  }
124 
126  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
127  std::vector<TensorNetwork> stack(degree()+1);
128  stack[0] = _solution;
129  stack[0].reduce_representation();
130 
131  const auto cSize = size();
132  for(size_t j = 0; j < cSize; ++j) {
133  size_t rebuildIndex = 0;
134 
135  if(j > 0) {
136  // Find the maximal recyclable stack position
137  for(; rebuildIndex < degree(); ++rebuildIndex) {
138  if(positions[j-1][rebuildIndex] != positions[j][rebuildIndex]) {
139  break;
140  }
141  }
142  }
143 
144  // Rebuild stack
145  for(size_t i = rebuildIndex; i < degree(); ++i) {
146  stack[i+1] = stack[i];
147  stack[i+1].fix_mode(0, positions[j][i]);
148  stack[i+1].reduce_representation();
149  }
150 
151  measuredValues[j] = stack.back()[0];
152  }
153  }
154 
155 
156  void SinglePointMeasurementSet::measure(std::function<value_t(const std::vector<size_t>&)> _callback) {
157  const auto cSize = size();
158  for(size_t i = 0; i < cSize; ++i) {
159  measuredValues[i] = _callback(positions[i]);
160  }
161  }
162 
163 
164  double SinglePointMeasurementSet::test(const Tensor& _solution) const {
165  const auto cSize = size();
166  double error = 0.0, norm = 0.0;
167  for(size_t i = 0; i < cSize; ++i) {
168  error += misc::sqr(measuredValues[i] - _solution[positions[i]]);
169  norm += misc::sqr(measuredValues[i]);
170  }
171  return std::sqrt(error/norm);
172  }
173 
174 
175  double SinglePointMeasurementSet::test(const TensorNetwork& _solution) const {
176  const auto cSize = size();
177  double error = 0.0, norm = 0.0;
178 
179  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
180  std::vector<TensorNetwork> stack(degree()+1);
181  stack[0] = _solution;
182  stack[0].reduce_representation();
183 
184  for(size_t j = 0; j < cSize; ++j) {
185  size_t rebuildIndex = 0;
186 
187  if(j > 0) {
188  // Find the maximal recyclable stack position
189  for(; rebuildIndex < degree(); ++rebuildIndex) {
190  if(positions[j-1][rebuildIndex] != positions[j][rebuildIndex]) {
191  break;
192  }
193  }
194  }
195 
196  // Rebuild stack
197  for(size_t i = rebuildIndex; i < degree(); ++i) {
198  stack[i+1] = stack[i];
199  stack[i+1].fix_mode(0, positions[j][i]);
200  stack[i+1].reduce_representation();
201  }
202 
203  error += misc::sqr(measuredValues[j] - stack.back()[0]);
204  norm += misc::sqr(measuredValues[j]);
205  }
206  return std::sqrt(error/norm);
207  }
208 
209 
210  double SinglePointMeasurementSet::test(std::function<value_t(const std::vector<size_t>&)> _callback) const {
211  const auto cSize = size();
212  double error = 0.0, norm = 0.0;
213  for(size_t i = 0; i < cSize; ++i) {
214  error += misc::sqr(measuredValues[i] - _callback(positions[i]));
215  norm += misc::sqr(measuredValues[i]);
216  }
217  return std::sqrt(error/norm);
218  }
219 
220 
221 
222  void SinglePointMeasurementSet::create_random_positions(const size_t _numMeasurements, const std::vector<size_t>& _dimensions) {
223  using ::xerus::misc::operator<<;
224  XERUS_REQUIRE(misc::product(_dimensions) >= _numMeasurements, "It's impossible to perform as many measurements as requested. " << _numMeasurements << " > " << _dimensions);
225 
226  // Create distributions
227  std::vector<std::uniform_int_distribution<size_t>> indexDist;
228  for (size_t i = 0; i < _dimensions.size(); ++i) {
229  indexDist.emplace_back(0, _dimensions[i]-1);
230  }
231 
232  std::set<size_t> measuredPositions;
233  std::vector<size_t> multIdx(_dimensions.size());
234  while (positions.size() < _numMeasurements) {
235  size_t pos = 0;
236  for (size_t i = 0; i < _dimensions.size(); ++i) {
237  multIdx[i] = indexDist[i](misc::randomEngine);
238  pos *= _dimensions[i]; pos += multIdx[i];
239  }
240  if (!misc::contains(measuredPositions, pos)) {
241  measuredPositions.insert(pos);
242  positions.push_back(multIdx);
243  }
244  }
245 
246  sort(true);
247  measuredValues.resize(_numMeasurements);
248  }
249 
250 
251 
252 
253 
254 
255  // --------------------- RankOneMeasurementSet -----------------
256 
257 
258  RankOneMeasurementSet::RankOneMeasurementSet(const SinglePointMeasurementSet& _other, const std::vector<size_t>& _dimensions) {
259  REQUIRE(_other.degree() == _dimensions.size(), "Inconsistent degrees.");
260  std::vector<Tensor> zeroPosition; zeroPosition.reserve(_dimensions.size());
261  for(size_t j = 0; j < _dimensions.size(); ++j) {
262  zeroPosition.emplace_back(Tensor({_dimensions[j]}));
263  }
264 
265  for(size_t i = 0; i < _other.size(); ++i) {
266  add(zeroPosition, _other.measuredValues[i]);
267  for(size_t j = 0; j < _other.degree(); ++j) {
268  positions.back()[j][_other.positions[i][j]] = 1.0;
269  }
270  }
271  }
272 
273  RankOneMeasurementSet RankOneMeasurementSet::random(const size_t _numMeasurements, const std::vector<size_t>& _dimensions) {
274  RankOneMeasurementSet result;
275  result.create_random_positions(_numMeasurements, _dimensions);
276  result.measuredValues.resize(_numMeasurements, 0);
277  return result;
278  }
279 
280 
281  RankOneMeasurementSet RankOneMeasurementSet::random(const size_t _numMeasurements, const Tensor& _solution) {
282  RankOneMeasurementSet result;
283  result.create_random_positions(_numMeasurements, _solution.dimensions);
284  result.measure(_solution);
285  return result;
286  }
287 
288  RankOneMeasurementSet RankOneMeasurementSet::random(const size_t _numMeasurements, const TensorNetwork& _solution) {
289  RankOneMeasurementSet result;
290  result.create_random_positions(_numMeasurements, _solution.dimensions);
291  result.measure(_solution);
292  return result;
293  }
294 
295  RankOneMeasurementSet RankOneMeasurementSet::random(const size_t _numMeasurements, const std::vector<size_t>& _dimensions, std::function<value_t(const std::vector<Tensor>&)> _callback) {
296  RankOneMeasurementSet result;
297  result.create_random_positions(_numMeasurements, _dimensions);
298  result.measure(_callback);
299  return result;
300  }
301 
302 
304  REQUIRE(positions.size() == measuredValues.size(), "Inconsitend SinglePointMeasurementSet encountered.");
305  return positions.size();
306  }
307 
308 
310  return positions.empty() ? 0 : positions[0].size();
311  }
312 
313  void RankOneMeasurementSet::add(const std::vector<Tensor>& _position, const value_t _measuredValue) {
314  IF_CHECK(
315  INTERNAL_CHECK(positions.size() == measuredValues.size(), "Internal Error.");
316  if(size() > 0) {
317  for(size_t i = 0; i < degree(); ++i) {
318  REQUIRE(positions.back()[i].dimensions == _position[i].dimensions, "Inconsitend dimensions obtained.");
319  }
320  }
321  for (const Tensor& t : _position) {
322  REQUIRE(t.degree() == 1, "Illegal measurement.");
323  }
324  );
325 
326  positions.emplace_back(_position);
327  measuredValues.emplace_back(_measuredValue);
328  }
329 
330  void RankOneMeasurementSet::sort(const bool _positionsOnly) {
331  const auto comperator = [](const std::vector<Tensor>& _lhs, const std::vector<Tensor>& _rhs) {
332  REQUIRE(_lhs.size() == _rhs.size(), "Inconsistent degrees in measurment positions.");
333  for (size_t i = 0; i < _lhs.size(); ++i) {
334  const auto res = internal::comp(_lhs[i], _rhs[i]);
335  if(res == -1) { return true; }
336  if(res == 1) { return false; }
337  }
338  return false; // equality
339  };
340 
341  if(_positionsOnly) {
342  std::sort(positions.begin(), positions.end(), comperator);
343  } else {
344  REQUIRE(positions.size() == measuredValues.size(), "Inconsitend SinglePointMeasurementSet encountered.");
346  }
347  }
348 
350  for(size_t i = 0; i < size(); ++i) {
351  for(size_t j = 0; j < degree(); ++j) {
352  const auto norm = positions[i][j].frob_norm();
353  positions[i][j] /= norm;
354  positions[i][j].apply_factor();
355  measuredValues[i] /= norm;
356  }
357  }
358  }
359 
361  const auto cSize = size();
362  double norm = 0.0;
363  for(size_t i = 0; i < cSize; ++i) {
364  norm += misc::sqr(measuredValues[i]);
365  }
366  return std::sqrt(norm);
367  }
368 
369 
370  void RankOneMeasurementSet::measure(const Tensor& _solution) {
371  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
372  std::vector<Tensor> stack(degree()+1);
373  stack[0] = _solution;
374 
375  const auto cSize = size();
376  for(size_t j = 0; j < cSize; ++j) {
377  size_t rebuildIndex = 0;
378 
379  if(j > 0) {
380  // Find the maximal recyclable stack position
381  for(; rebuildIndex < degree(); ++rebuildIndex) {
382  if(!approx_equal(positions[j-1][rebuildIndex], positions[j][rebuildIndex])) {
383  break;
384  }
385  }
386  }
387 
388  // Rebuild stack
389  for(size_t i = rebuildIndex; i < degree(); ++i) {
390  contract(stack[i+1], positions[j][i], false, stack[i], false, 1);
391  }
392 
393  measuredValues[j] = stack.back()[0];
394  }
395  }
396 
398  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
399  std::vector<TensorNetwork> stack(degree()+1);
400  stack[0] = _solution;
401  stack[0].reduce_representation();
402 
403  Index l, k;
404 
405  const auto cSize = size();
406  for(size_t j = 0; j < cSize; ++j) {
407  size_t rebuildIndex = 0;
408 
409  if(j > 0) {
410  // Find the maximal recyclable stack position
411  for(; rebuildIndex < degree(); ++rebuildIndex) {
412  if(!approx_equal(positions[j-1][rebuildIndex], positions[j][rebuildIndex])) {
413  break;
414  }
415  }
416  }
417 
418  // Rebuild stack
419  for(size_t i = rebuildIndex; i < degree(); ++i) {
420  stack[i+1](k&0) = positions[j][i](l) * stack[i](l, k&1);
421  stack[i+1].reduce_representation();
422  }
423 
424  measuredValues[j] = stack.back()[0];
425  }
426  }
427 
428 
429  void RankOneMeasurementSet::measure(std::function<value_t(const std::vector<Tensor>&)> _callback) {
430  const auto cSize = size();
431  for(size_t i = 0; i < cSize; ++i) {
432  measuredValues[i] = _callback(positions[i]);
433  }
434  }
435 
436 
437  double RankOneMeasurementSet::test(const Tensor& _solution) const {
438  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
439  const auto cSize = size();
440  double error = 0.0, norm = 0.0;
441 
442  std::vector<Tensor> stack(degree()+1);
443  stack[0] = _solution;
444 
445  for(size_t j = 0; j < cSize; ++j) {
446  size_t rebuildIndex = 0;
447 
448  if(j > 0) {
449  // Find the maximal recyclable stack position
450  for(; rebuildIndex < degree(); ++rebuildIndex) {
451  if(!approx_equal(positions[j-1][rebuildIndex], positions[j][rebuildIndex])) {
452  break;
453  }
454  }
455  }
456 
457  // Rebuild stack
458  for(size_t i = rebuildIndex; i < degree(); ++i) {
459  contract(stack[i+1], positions[j][i], false, stack[i], false, 1);
460  }
461 
462  error += misc::sqr(measuredValues[j] - stack.back()[0]);
463  norm += misc::sqr(measuredValues[j]);
464  }
465 
466  return std::sqrt(error/norm);
467  }
468 
469 
470  double RankOneMeasurementSet::test(const TensorNetwork& _solution) const {
471  REQUIRE(_solution.degree() == degree(), "Degrees of solution and measurements must match!");
472  const auto cSize = size();
473  const Index l, k;
474 
475  double error = 0.0, norm = 0.0;
476 
477  #pragma omp parallel reduction(+:error, norm)
478  {
479  std::vector<TensorNetwork> stack(degree()+1);
480  stack[degree()] = _solution;
481  stack[degree()].reduce_representation();
482 
483  bool init = true;
484  #pragma omp for
485  for(size_t j = 0; j < cSize; ++j) {
486  size_t unchangedModes = 0;
487 
488  if(!init) {
489  // Find the maximal recyclable stack position
490  for(; unchangedModes < degree(); ++unchangedModes) {
491  if(!approx_equal(positions[j-1][degree()-1-unchangedModes], positions[j][degree()-1-unchangedModes])) { break; }
492  }
493  } else { init = false; }
494 
495  // Rebuild stack
496  for(long i = long(degree())-1-long(unchangedModes); i >= 0; --i) {
497  stack[size_t(i)](k&0) = stack[size_t(i+1)](k&1, l) * positions[j][size_t(i)](l);
498  stack[size_t(i)].reduce_representation();
499  }
500 
501  error += misc::sqr(measuredValues[j] - stack.front()[0]);
502  norm += misc::sqr(measuredValues[j]);
503  }
504  }
505 
506  return std::sqrt(error/norm);
507  }
508 
509 
510  double RankOneMeasurementSet::test(std::function<value_t(const std::vector<Tensor>&)> _callback) const {
511  const auto cSize = size();
512  double error = 0.0, norm = 0.0;
513  for(size_t i = 0; i < cSize; ++i) {
514  error += misc::sqr(measuredValues[i] - _callback(positions[i]));
515  norm += misc::sqr(measuredValues[i]);
516  }
517  return std::sqrt(error/norm);
518  }
519 
520 
521 
522  void RankOneMeasurementSet::create_random_positions(const size_t _numMeasurements, const std::vector<size_t>& _dimensions) {
523  using ::xerus::misc::operator<<;
524  XERUS_REQUIRE(misc::product(_dimensions) >= _numMeasurements, "It's impossible to perform as many measurements as requested. " << _numMeasurements << " > " << _dimensions);
525 
526  // Create distributions
527  std::vector<std::uniform_int_distribution<size_t>> indexDist;
528  for (size_t i = 0; i < _dimensions.size(); ++i) {
529  indexDist.emplace_back(0, _dimensions[i]-1);
530  }
531 
532  std::vector<Tensor> randOnePosition(_dimensions.size());
533  while (positions.size() < _numMeasurements) {
534  for (size_t i = 0; i < _dimensions.size(); ++i) {
535  randOnePosition[i] = Tensor::random({_dimensions[i]});
536  }
537 
538  // NOTE Assuming our random generator works, no identical positions should occour.
539  positions.push_back(randOnePosition);
540  }
541 
542  sort(true);
543  measuredValues.resize(_numMeasurements);
544  }
545 
546 
547 
548  namespace internal {
549  int comp(const Tensor& _a, const Tensor& _b) {
550  REQUIRE(_a.dimensions == _b.dimensions, "Compared Tensors must have the same dimensions.");
551 
552  if(_a.is_dense() || _b.is_dense()) {
553  for(size_t k = 0; k < _a.size; ++k) {
554  if (_a.cat(k) < _b.cat(k)) { return 1; }
555  if (_a.cat(k) > _b.cat(k)) { return -1; }
556  }
557  return 0;
558  }
559  INTERNAL_CHECK(!_a.has_factor(), "IE");
560  INTERNAL_CHECK(!_b.has_factor(), "IE");
561 
562  const std::map<size_t, double>& dataA = _a.get_unsanitized_sparse_data();
563  const std::map<size_t, double>& dataB = _b.get_unsanitized_sparse_data();
564 
565  auto itrA = dataA.begin();
566  auto itrB = dataB.begin();
567 
568  while(itrA != dataA.end() && itrB != dataB.end()) {
569  if(itrA->first == itrB->first) {
570  if(itrA->second < itrB->second) {
571  return 1;
572  }
573  if(itrA->second > itrB->second) {
574  return -1;
575  }
576  ++itrA; ++itrB;
577  } else if(itrA->first < itrB->first) {
578  if(itrA->second < 0.0) {
579  return 1;
580  }
581  if(itrA->second > 0.0) {
582  return -1;
583  }
584  ++itrA;
585  } else { // itrA->first > itrB->first
586  if(0.0 < itrB->second) {
587  return 1;
588  }
589  if(0.0 > itrB->second) {
590  return -1;
591  }
592  ++itrB;
593  }
594  }
595 
596  while(itrA != dataA.end()) {
597  if(itrA->second < 0.0) {
598  return 1;
599  }
600  if(itrA->second > 0.0) {
601  return -1;
602  }
603  ++itrA;
604  }
605 
606  while(itrB != dataB.end()) {
607  if(0.0 < itrB->second) {
608  return 1;
609  }
610  if(0.0 > itrB->second) {
611  return -1;
612  }
613  ++itrB;
614  }
615 
616  return 0;
617  }
618  } // namespace internal
619 
620 } // namespace xerus
void simultaneous_sort(std::vector< KeyType > &_keyVector, std::vector< DataType > &_dataVector, Comparator _comp)
Definition: sort.h:52
Header file for CHECK and REQUIRE macros.
void sort(const bool _positionsOnly=false)
Definition: measurments.cpp:89
static RankOneMeasurementSet random(const size_t _numMeasurements, const std::vector< size_t > &_dimensions)
size_t degree() const
Returns the degree of the tensor.
Definition: tensor.cpp:206
double test(const Tensor &_solution) const
Header file for the TTNetwork class (and thus TTTensor and TTOperator).
Header file for the Index class.
#define REQUIRE
Definition: internal.h:33
static Tensor XERUS_warn_unused random(DimensionTuple _dimensions, distribution &_dist=xerus::misc::defaultNormalDistribution, generator &_rnd=xerus::misc::randomEngine)
Constructs a dense Tensor with the given dimensions and uses the given random generator and distribut...
Definition: tensor.h:213
Very general class used to represent arbitary tensor networks.
Definition: tensorNetwork.h:42
Class used to represent a single point measurments.
Definition: measurments.h:43
size_t size
Size of the Tensor – always equal to the product of the dimensions.
Definition: tensor.h:102
DimensionTuple dimensions
Vector containing the individual dimensions of the tensor.
Definition: tensor.h:99
#define IF_CHECK
Definition: internal.h:35
void measure(const Tensor &_solution)
The main namespace of xerus.
Definition: basic.h:37
Class that handles simple (non-decomposed) tensors in a dense or sparse representation.
Definition: tensor.h:70
value_t cat(const size_t _position) const
Unsanitized read access to a single entry.
Definition: tensor.cpp:384
std::map< size_t, value_t > & get_unsanitized_sparse_data()
Gives access to the internal sparse map, without any checks.
Definition: tensor.cpp:445
double test(const Tensor &_solution) const
std::vector< value_t > measuredValues
Definition: measurments.h:97
Header file for the different measurment classes.
Header file for some extended sorting functions.
void reduce_representation()
Contracts all nodes that are joined by a full-rank edge.
size_t degree() const
Gets the degree of the TensorNetwork.
void add(const std::vector< Tensor > &_position, const value_t _measuredValue)
Header file for the Tensor class.
void contract(Tensor &_result, const Tensor &_lhs, const bool _lhsTrans, const Tensor &_rhs, const bool _rhsTrans, const size_t _numModes)
Low-level contraction between Tensors.
Definition: tensor.cpp:1252
bool has_factor() const
Checks whether the tensor has a non-trivial global scaling factor.
Definition: tensor.cpp:211
void sort(const bool _positionsOnly)
int comp(const Tensor &_a, const Tensor &_b)
#define XERUS_REQUIRE(condition, message)
Checks whether condition is true. logs an error otherwise via XERUS_LOG(error, message).
Definition: check.h:65
Header file for comfort functions and macros that should not be exported in the library.
constexpr T sqr(const T &_a) noexcept
: Calculates _a*_a.
Definition: math.h:43
double value_t
The type of values to be used by xerus.
Definition: basic.h:43
Class used to represent indices that can be used to write tensor calculations in index notation...
Definition: index.h:43
bool is_dense() const
Returns whether the current representation is dense.
Definition: tensor.cpp:220
std::vector< std::vector< size_t > > positions
Definition: measurments.h:45
bool approx_equal(const xerus::Tensor &_a, const xerus::Tensor &_b, const xerus::value_t _eps=EPSILON)
Checks whether two tensors are approximately equal.
Definition: tensor.cpp:1738
static SinglePointMeasurementSet random(const size_t _numMeasurements, const std::vector< size_t > &_dimensions)
Definition: measurments.cpp:42
thread_local std::mt19937_64 randomEngine
#define INTERNAL_CHECK
Definition: internal.h:37
Header file for some additional math functions.
void measure(const Tensor &_solution)
void add(std::vector< size_t > _position, const value_t _measuredValue)
Definition: measurments.cpp:83
Header file for the TensorNetwork class.
std::vector< value_t > measuredValues
Definition: measurments.h:46
Header file for the IndexedTensor class.
std::vector< size_t > dimensions
Dimensions of the external indices, i.e. the dimensions of the tensor represented by the network...