xerus
a general purpose tensor library
indexedTensorReadOnly.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 
27 
28 #include <xerus/index.h>
29 
31 #include <xerus/misc/check.h>
32 #include <xerus/misc/internal.h>
33 #include <xerus/tensor.h>
34 #include <xerus/tensorNetwork.h>
35 
36 namespace xerus {
37  namespace internal {
38  /*- - - - - - - - - - - - - - - - - - - - - - - - - - Constructors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
39 
40  template<class tensor_type>
42  tensorObjectReadOnly(_other.tensorObjectReadOnly),
43  indices(std::move(_other.indices))
44  { }
45 
46 
47  template<class tensor_type>
48  IndexedTensorReadOnly<tensor_type>::IndexedTensorReadOnly(const tensor_type* const _tensorObjectReadOnly, std::vector<Index> _indices)
49  : tensorObjectReadOnly(_tensorObjectReadOnly), indices(std::move(_indices)) { }
50 
51  /*- - - - - - - - - - - - - - - - - - - - - - - - - - Destructor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
52 
53  template<class tensor_type>
55 
56 
57  /*- - - - - - - - - - - - - - - - - - - - - - - - - - Others - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
58 
59  template<class tensor_type>
61  REQUIRE(degree() == 0, "cannot cast tensors of degree > 0 to value_t. did you mean frob_norm() or similar?");
62  return (*tensorObjectReadOnly)[0];
63  }
64 
65  template<class tensor_type>
66  bool IndexedTensorReadOnly<tensor_type>::uses_tensor(const tensor_type *_otherTensor) const {
67  return _otherTensor == tensorObjectReadOnly;
68  }
69 
70  template<class tensor_type>
72  return tensorObjectReadOnly->degree();
73  }
74 
75  template<class tensor_type>
77  assign_indices(degree());
78  }
79 
80  template<class tensor_type>
82  if(!indicesAssigned) {
83  size_t dimensionCount = 0;
84  for(size_t i = 0; i < indices.size(); ++i) {
85  Index& idx = indices[i];
86 
87  // Set span
88  idx.set_span(_degree);
89 
90  dimensionCount += idx.span;
91 
92  if(!idx.fixed()) {
93  // Determine whether the index is open
94  bool open = true;
95  for(size_t j = 0; j < i; ++j) {
96  if(indices[j] == idx) {
97  REQUIRE(indices[j].open(), "An index must not appere more than twice!");
98  indices[j].open(false);
99  open = false;
100  break;
101  }
102  }
103 
104  if(open) { idx.open(true); }
105  }
106  IF_CHECK(idx.flags[Index::Flag::ASSINGED] = true;)
107  }
108 
109  REQUIRE(dimensionCount >= _degree, "Order determined by Indices is to small. Order according to the indices " << dimensionCount << ", according to the tensor " << _degree);
110  REQUIRE(dimensionCount <= _degree, "Order determined by Indices is to large. Order according to the indices " << dimensionCount << ", according to the tensor " << _degree);
111 
112  misc::erase(indices, [](const Index& _idx) { return _idx.span == 0; });
113  indicesAssigned = true;
114  }
115  }
116 
117  template<class tensor_type>
119  INTERNAL_CHECK(indicesAssigned, "bla");
120 
121  size_t dimensionCount = 0;
122  for(size_t i = 0; i < indices.size(); ++i) {
123  Index& idx = indices[i];
124 
125  // Calculate multDimension
126  REQUIRE(dimensionCount+idx.span <= tensorObjectReadOnly->dimensions.size(), "Order determined by Indices is to large: " << dimensionCount+idx.span << " > " << tensorObjectReadOnly->dimensions.size());
127  idx.assingedDimension = 1;
128  for(size_t j = 0; j < idx.span; ++j) {
129  idx.assingedDimension *= tensorObjectReadOnly->dimensions[dimensionCount++];
130  }
131  }
132 
133  REQUIRE(dimensionCount >= degree(), "Order determined by Indices is to small. Order according to the indices " << dimensionCount << ", according to the tensor " << degree());
134  REQUIRE(dimensionCount <= degree(), "Order determined by Indices is to large. Order according to the indices " << dimensionCount << ", according to the tensor " << degree());
135  }
136 
137 
138  template<class tensor_type>
139  std::vector<size_t> IndexedTensorReadOnly<tensor_type>::get_evaluated_dimensions(const std::vector<Index>& _indexOrder) {
140  std::vector<size_t> evalDimensions;
141  evalDimensions.reserve(_indexOrder.size());
142 
143  // Find the order that this tensor has using the current indices
144  assign_indices();
145  size_t trueOrder = 0;
146  for(const Index& idx : indices) {
147  if(idx.open()) {trueOrder += idx.span; }
148  }
149 
150  // Find dimensions for all given indices
151  for(const Index& idx : _indexOrder) {
152  if(idx.actual_span(trueOrder) == 0) { continue; }
153 
154  REQUIRE(misc::count(indices, idx) == 1, "All indices of evaluation target must appear exactly once. Here " << misc::count(indices, idx) << " " << indices << " " << _indexOrder);
155 
156  // Find index
157  size_t indexPos = 0, dimCount = 0;
158  while(indices[indexPos] != idx) {
159  dimCount += indices[indexPos++].span;
160  }
161 
162  REQUIRE(indices[indexPos].open(), "Index appearing on the LHS of assignment must be open on RHS");
163  REQUIRE(dimCount+indices[indexPos].span <= tensorObjectReadOnly->dimensions.size(), "Order determined by Indices is to large. Tensor has " << tensorObjectReadOnly->dimensions.size() << " indices at least " << dimCount+indices[indexPos].span);
164 
165  // Insert dimensions
166  for(size_t i = 0; i < indices[indexPos].span; ++i) {
167  evalDimensions.emplace_back(tensorObjectReadOnly->dimensions[dimCount+i]);
168  }
169  }
170  return evalDimensions;
171  }
172 
173 
174  // IndexedTensorReadOnly may be instanciated as
175  template class IndexedTensorReadOnly<Tensor>;
177 
178 
179  /*- - - - - - - - - - - - - - - - - - - - - - - - - - Aritmetic Operators - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
180 
181  template<class tensor_type>
183  IndexedTensorMoveable<tensor_type> result(std::move(_tensor));
184  *result.tensorObject *= _factor;
185  return result;
186  }
187 
188  template IndexedTensorMoveable<Tensor> operator*<Tensor>(const value_t _factor, IndexedTensorReadOnly<Tensor>&& _tensor);
190 
191 
192  template<class tensor_type>
194  return operator*(_factor, std::move(_tensor));
195  }
196 
199 
200 
201  template<class tensor_type>
203  IndexedTensorMoveable<tensor_type> result(std::move(_tensor));
204  *result.tensorObject /= _divisor;
205  return result;
206  }
207 
210 
211 
213  IndexedTensorMoveable<Tensor> result(std::move(_lhs));
214  result.perform_traces();
215  result.indexed_plus_equal(std::move(_rhs));
216  return result;
217  }
218 
220  IndexedTensorMoveable<Tensor> result(std::move(_lhs));
221  result.perform_traces();
222  result.indexed_plus_equal(std::move(_rhs));
223  return result;
224  }
225 
227  return operator+(std::move(_rhs), std::move(_lhs));
228  }
229 
231  return operator+(std::move(_lhs), static_cast<IndexedTensorReadOnly<Tensor>&&>(_rhs));
232  }
233 
234 
236  IndexedTensorMoveable<Tensor> result(std::move(_lhs));
237  result.perform_traces();
238  result.indexed_minus_equal(std::move(_rhs));
239  return result;
240  }
241 
243  IndexedTensorMoveable<Tensor> result(std::move(_lhs));
244  result.perform_traces();
245  result.indexed_minus_equal(std::move(_rhs));
246  return result;
247  }
248 
250  return (-1.0)*operator-(std::move(_rhs), std::move(_lhs));
251  }
252 
254  return operator-(std::move(_lhs), static_cast<IndexedTensorReadOnly<Tensor>&&>(_rhs));
255  }
256 
257 
258 
260  std::unique_ptr<IndexedTensorMoveable<TensorNetwork>> result;
261  if(!_lhs.tensorObjectReadOnly->specialized_sum(result, std::move(_lhs), std::move(_rhs))
262  && !_rhs.tensorObjectReadOnly->specialized_sum(result, std::move(_rhs), std::move(_lhs))) {
263  result.reset( new IndexedTensorMoveable<TensorNetwork>(IndexedTensorMoveable<Tensor>(std::move(_lhs)) + IndexedTensorMoveable<Tensor>(std::move(_rhs))));
264  }
265  return std::move(*result);
266  }
267 
269  return std::move(_lhs)+IndexedTensorMoveable<Tensor>(std::move(_rhs));
270  }
271 
273  return IndexedTensorMoveable<Tensor>(std::move(_lhs))+std::move(_rhs);
274  }
275 
277  return std::move(_lhs)+(-1*std::move(_rhs));
278  }
279 
281  return std::move(_lhs)-IndexedTensorMoveable<Tensor>(std::move(_rhs));
282  }
283 
285  return IndexedTensorMoveable<Tensor>(std::move(_lhs))-std::move(_rhs);
286  }
287 
288 
289 
291  std::unique_ptr<IndexedTensorMoveable<TensorNetwork>> result(new IndexedTensorMoveable<TensorNetwork>());
292  if(!_lhs.tensorObjectReadOnly->specialized_contraction(result, std::move(_lhs), std::move(_rhs)) && !_rhs.tensorObjectReadOnly->specialized_contraction(result, std::move(_rhs), std::move(_lhs))) {
293  _lhs.assign_indices();
294  result->tensorObject = new TensorNetwork(*_lhs.tensorObjectReadOnly);
295  result->tensorObjectReadOnly = result->tensorObject;
296  result->indices = _lhs.indices;
297  result->deleteTensorObject = true;
298  TensorNetwork::add_network_to_network(std::move(*result), std::move(_rhs));
299  }
300  return std::move(*result);
301  }
302 
303 
305  std::unique_ptr<IndexedTensorMoveable<TensorNetwork>> result(new IndexedTensorMoveable<TensorNetwork>());
306  if(!_lhs.tensorObjectReadOnly->specialized_contraction(result, std::move(_lhs), std::move(_rhs)) && !_rhs.tensorObjectReadOnly->specialized_contraction(result, std::move(_rhs), std::move(_lhs))) {
307  _lhs.assign_indices();
308  result->tensorObject = _lhs.tensorObject;
309  result->tensorObjectReadOnly = _lhs.tensorObjectReadOnly;
310  result->indices = _lhs.indices;
311  result->deleteTensorObject = true;
312  _lhs.deleteTensorObject = false;
313  TensorNetwork::add_network_to_network(std::move(*result), std::move(_rhs));
314  }
315  return std::move(*result);
316  }
317 
319  return operator*(std::move(_rhs), std::move(_lhs));
320  }
321 
323  return operator*(std::move(_lhs), static_cast<IndexedTensorReadOnly<TensorNetwork>&&>(_rhs));
324  }
325 
326 
327  /*- - - - - - - - - - - - - - - - - - - - - - - - - - External functions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
328 
329  template<class tensor_type>
331  return _idxTensor.tensorObjectReadOnly->frob_norm();
332  }
333 
334  template value_t frob_norm<Tensor>(const IndexedTensorReadOnly<Tensor>& _idxTensor);
336 
338  return _idxTensor.tensorObjectReadOnly->one_norm();
339  }
340 
341  size_t get_eval_degree(const std::vector<Index>& _indices) {
342  size_t degree = 0;
343  for(const Index& idx : _indices) {
344  INTERNAL_CHECK(idx.flags[Index::Flag::ASSINGED], "Internal Error");
345  if(!idx.fixed() && misc::count(_indices, idx) != 2) { degree += idx.span; }
346  }
347  return degree;
348  }
349  } // namespace internal
350 } // namespace xerus
Header file for CHECK and REQUIRE macros.
void indexed_plus_equal(IndexedTensorReadOnly< tensor_type > &&_rhs)
Tensor add_assignment with indices.
Internal representation of an read and write and moveable indexed Tensor or TensorNetwork.
Header file for the Index class.
Header file for the IndexedTensorReadOnly class.
Header file for the IndexedTensorMoveable class.
Header file for the standard contaienr support functions.
IndexedTensorMoveable< Tensor > operator+(IndexedTensorReadOnly< Tensor > &&_lhs, IndexedTensorReadOnly< Tensor > &&_rhs)
#define REQUIRE
Definition: internal.h:33
Very general class used to represent arbitary tensor networks.
Definition: tensorNetwork.h:42
bool open() const
Checks whether the index is open.
Definition: index.cpp:111
Internal representation of an readable indexed Tensor or TensorNetwork.
#define IF_CHECK
Definition: internal.h:35
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
STL namespace.
void indexed_minus_equal(IndexedTensorReadOnly< tensor_type > &&_rhs)
Tensor subtract_assignment with indices.
void perform_traces()
: Performes all traces induces by the current indices and therby also evaluates all fixed indices...
template value_t frob_norm< Tensor >(const IndexedTensorReadOnly< Tensor > &_idxTensor)
Header file for the Tensor class.
double one_norm(const double *const _x, const size_t _n)
: Computes the one norm =||x||_1
tensor_type * tensorObject
Non-const pointer to the tensor object.
std::bitset< NUM_FLAGS > flags
Bitset of all possible flags the index may possess.
Definition: index.h:71
size_t get_eval_degree(const std::vector< Index > &_indices)
void set_span(const size_t _degree)
Returns the span this index actually represents in a tensor of given order.
Definition: index.cpp:64
size_t assingedDimension
The product of the external dimensions this index correstponds to. Only set for assinged indices...
Definition: index.h:68
IndexedTensorMoveable< Tensor > operator-(IndexedTensorReadOnly< Tensor > &&_lhs, IndexedTensorReadOnly< Tensor > &&_rhs)
size_t degree() const
Returns the degree of the associated tensorObejct.
Header file for comfort functions and macros that should not be exported in the library.
value_t frob_norm(const IndexedTensorReadOnly< tensor_type > &_idxTensor)
Returns the frobenious norm of the associated tensorObejct.
template IndexedTensorMoveable< TensorNetwork > operator/(IndexedTensorReadOnly< TensorNetwork > &&_tensor, const value_t _divisor)
double value_t
The type of values to be used by xerus.
Definition: basic.h:43
template IndexedTensorMoveable< TensorNetwork > operator*(IndexedTensorReadOnly< TensorNetwork > &&_tensor, const value_t _factor)
Class used to represent indices that can be used to write tensor calculations in index notation...
Definition: index.h:43
#define INTERNAL_CHECK
Definition: internal.h:37
size_t span
The span states how many dimensions are covered by the index.
Definition: index.h:65
bool fixed() const
Checks whether the Index represents a fixed number.
Definition: index.cpp:96
Header file for the TensorNetwork class.
const tensor_type * tensorObjectReadOnly
Pointer to the associated Tensor/TensorNetwork object.
template value_t frob_norm< TensorNetwork >(const IndexedTensorReadOnly< TensorNetwork > &_idxTensor)
IndexedTensorReadOnly()=delete
There is no usefull default constructor.