tensorNetwork.h 22.7 KB
Newer Older
Baum's avatar
Baum committed
1
// Xerus - A General Purpose Tensor Library
2
// Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf. 
Baum's avatar
Baum committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 
// Xerus is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
// 
// Xerus 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 Affero General Public License for more details.
// 
// You should have received a copy of the GNU Affero General Public License
// along with Xerus. If not, see <http://www.gnu.org/licenses/>.
//
// For further information on Xerus visit https://libXerus.org 
// or contact us at contact@libXerus.org.

20
/**
21 22 23
* @file
* @brief Header file for the TensorNetwork class.
*/
24

Baum's avatar
Baum committed
25 26
#pragma once

Sebastian Wolf's avatar
Sebastian Wolf committed
27
#include <set>
28
#include <memory>
29
#include "misc/fileIO.h"
Sebastian Wolf's avatar
Sebastian Wolf committed
30
 
Sebastian Wolf's avatar
Sebastian Wolf committed
31 32
#include "indexedTensor.h"

Baum's avatar
Baum committed
33
namespace xerus {
34 35
	// Necessary forward declaritons
	class Tensor;
Sebastian Wolf's avatar
Sebastian Wolf committed
36
	
Sebastian Wolf's avatar
Sebastian Wolf committed
37
	/** 
38
	* @brief Very general class used to represent arbitary tensor networks. 
Sebastian Wolf's avatar
Sebastian Wolf committed
39 40 41
	* @details Used as a basis for tensor decompositions like the TTNetwork but also used for the lazy evaluation of Tensor contractions.
	*/
	class TensorNetwork {
42
	public:
43
		///@brief: Represention of the ranks of a TensorNetwork.
Sebastian Wolf's avatar
Sebastian Wolf committed
44 45
		using RankTuple = std::vector<size_t>; 
		
46
		/**
47
		* @brief Class representing a link from a TensorNode to another node or an external index.
48
		*/
49
		class Link final {
50 51
		public:
			///@brief The index of the otherNode this Link links to.
52 53
			size_t other; 
			
54
			///@brief IndexPosition on the other node or index of external index.
55 56
			size_t indexPosition;
			
57
			///@brief Dimension of the link, always equals to other->tensorObject->dimensions[indexPosition].
58 59
			size_t dimension;
			
60
			///@brief Flag indicating whether this link correspond to an external index.
61 62
			bool external;
			
Fuchsi*'s avatar
Fuchsi* committed
63 64 65
			Link() noexcept = default;
			Link(const Link& ) noexcept = default;
			Link(      Link&&) noexcept = default;
66
			
Fuchsi*'s avatar
Fuchsi* committed
67
			Link(const size_t _other, const size_t _indexPos, const size_t _dim, const bool _external) noexcept;
68
			
Fuchsi*'s avatar
Fuchsi* committed
69 70
			Link& operator=(const Link& ) noexcept = default;
			Link& operator=(      Link&&) noexcept = default;
71
			
72
			/**
73 74 75 76
			* @brief Checks whether this link links to a particular node
			* @param _other the other node for which the linkage shall be checked
			* @return TRUE if _other is the target of this Link, FALSE otherwise.
			*/
Fuchsi*'s avatar
Fuchsi* committed
77
			bool links(const size_t _other) const noexcept;
78
		};
79 80
		
		
81 82 83
		/**
		* @brief The TensorNode class is used by the class TensorNetwork to store the componentent tensors defining the network.
		*/
84
		class TensorNode final {
85
		public:
86
			///@brief Save slot for the tensorObject associated with this node.
87 88
			std::unique_ptr<Tensor> tensorObject;
			
89
			///@brief Vector of links defining the connection of this node to the network.
90 91
			std::vector<Link> neighbors;
			
92
			///@brief Internal Flag
93
			bool erased;
94 95 96
			
			explicit TensorNode();
			
97
			TensorNode(const TensorNode&  _other);
Fuchsi*'s avatar
Fuchsi* committed
98
			TensorNode(      TensorNode&& _other) noexcept = default;
99 100 101
			
			explicit TensorNode(      std::unique_ptr<Tensor>&& _tensorObject);
			
102
			explicit TensorNode(std::unique_ptr<Tensor>&& _tensorObject, std::vector<Link> _neighbors);
103
			
104 105
			~TensorNode();
			
106
			TensorNode& operator=(const TensorNode&  _other);
Fuchsi*'s avatar
Fuchsi* committed
107
			TensorNode& operator=(      TensorNode&& _other) noexcept;
108 109 110 111 112

			TensorNode strippped_copy() const;
			
			// All getters are written without the use of tensorObject so that they also work for empty nodes
			
Fuchsi*'s avatar
Fuchsi* committed
113
			size_t size() const noexcept;
114
			
Fuchsi*'s avatar
Fuchsi* committed
115
			size_t degree() const noexcept;
116
			
Fuchsi*'s avatar
Fuchsi* committed
117
			void erase() noexcept;
118
		};
119
		
Sebastian Wolf's avatar
Sebastian Wolf committed
120
	protected:
121
		
Sebastian Wolf's avatar
Sebastian Wolf committed
122 123 124 125 126 127 128
		/** 
		 * @brief Internal indicator to prevent the creation of an degree zero node in TensorNetwork constructor.
		 */
		enum class ZeroNode : bool { None, Add };
		
		
	public:
129 130 131 132 133 134
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Member variables - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
			
		///@brief Dimensions of the external indices, i.e. the dimensions of the tensor represented by the network.
		std::vector<size_t> dimensions;
		
		///@brief The nodes constituting the network. The order determines the ids of the nodes.
Baum's avatar
Baum committed
135
		std::vector<TensorNode> nodes;
136 137 138 139 140 141 142
			
		///@brief The open links of the network in order.
		std::vector<Link> externalLinks;
		
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Constructors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
			
		/** 
143
		* @brief Constructs an order zero TensorNetwork.
144
		* @details The order of an empty TN is zero.
Sebastian Wolf's avatar
Sebastian Wolf committed
145
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
146
		explicit TensorNetwork();
147
		
148 149
		
		///@brief Copy Constructor
150
		TensorNetwork(const TensorNetwork& _cpy) = default;
151
		
Sebastian Wolf's avatar
Sebastian Wolf committed
152
		
153
		///@brief Move Constructor
Fuchsi*'s avatar
Fuchsi* committed
154
		TensorNetwork(TensorNetwork&& _mv) noexcept = default;
155
		
Sebastian Wolf's avatar
Sebastian Wolf committed
156
		
Sebastian Wolf's avatar
Sebastian Wolf committed
157 158 159
		/** 
		* @brief Constructs the trivial TensorNetwork containing the given Tensor as single node.
		*/
160
		TensorNetwork(Tensor _other);
161
		
Sebastian Wolf's avatar
Sebastian Wolf committed
162
		
Sebastian Wolf's avatar
Sebastian Wolf committed
163 164 165 166
		/** 
		* @brief Constructs the trivial TensorNetwork containing the given Tensor as single node.
		* The TN takes the ownership of the pointer.
		*/
167
		TensorNetwork(std::unique_ptr<Tensor>&&  _tensor);
168
		
Sebastian Wolf's avatar
Sebastian Wolf committed
169
		
Sebastian Wolf's avatar
Sebastian Wolf committed
170
		/** 
Sebastian Wolf's avatar
Sebastian Wolf committed
171
		* @brief Constructs the trivial TensorNetwork containing a Tensor with the given degree.
172
		* @details All dimensions are set equals one and the only entry 
Sebastian Wolf's avatar
Sebastian Wolf committed
173 174
		* of the tensor is zero.
		*/
175
		TensorNetwork(size_t _degree);
176
		
Sebastian Wolf's avatar
Sebastian Wolf committed
177 178 179
		/** 
		 * @brief (Internal) Constructs an order zero TensorNetwork.
		 * @details The order of an empty TN is zero.
180
		 * @param _nodeStatus defines whether the network will contain one degree zero node with the single
Sebastian Wolf's avatar
Sebastian Wolf committed
181 182 183 184 185
		 * entry zero.
		 */
		explicit TensorNetwork(const ZeroNode _nodeStatus);
		
		
186
		///@brief Destructor
187
		virtual ~TensorNetwork() = default;
188
		
Sebastian Wolf's avatar
Sebastian Wolf committed
189
		
190
		/** 
Sebastian Wolf's avatar
Sebastian Wolf committed
191
		* @brief Returns a new copy of the network.
192
		* @details All dimensions are set equals to one and the only entry 
Sebastian Wolf's avatar
Sebastian Wolf committed
193 194
		* of the tensor is zero.
		*/
Baum's avatar
Baum committed
195
		virtual TensorNetwork* get_copy() const;
196
			
197
	protected:
198
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Internal Helper functions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
199
		///@brief: Sets the externalLinks and returns an Link vector for a node, assuming that this node is the only node there is and all given dimensions are open.
200
		std::vector<Link> init_from_dimension_array();
201
		
Sebastian Wolf's avatar
Sebastian Wolf committed
202 203 204 205 206 207 208 209 210 211 212
		
		/** 
		 * @brief Creates a dataless copy of a subnet.
		 * @details Creates a copy of this TensorNetwork containing the specified nodes,
		 * but does not propagate the data. Instead it uses the nullptr as data for all nodes.
		 * @param _idF a function returning true if its argument should be part of the stripped subnet. defaults to selecting all nodes.
		 * @return the new TensorNetwork.
		 */
		TensorNetwork stripped_subnet(const std::function<bool(size_t)>& _idF = [](size_t){ return true;}) const;
		
		
Sebastian Wolf's avatar
Sebastian Wolf committed
213 214 215
		/** 
		* @brief Contracts all nodes that are not connected to any external links.
		*/
216
		virtual void contract_unconnected_subnetworks();
Sebastian Wolf's avatar
Sebastian Wolf committed
217 218
		
		
219 220 221 222 223 224 225 226
		/**
		 * @brief Performs all traces in the given node.
		 * @param _nodeId id of the node for which the traces shall be performed.
		 */
		void perform_traces(const size_t _nodeId);
		
	public:
		
Sebastian Wolf's avatar
Sebastian Wolf committed
227 228 229 230 231 232
		/** 
		 * @brief Finds the position of a single common edge between two nodes.
		 * @param _nodeA The first node.
		 * @param _nodeB The second node.
		 * @return Tuple containing the two positions in @a _nodeA and @a _nodeB.
		 */
233
		std::pair<size_t, size_t> find_common_edge(const size_t _nodeA, const size_t _nodeB) const;
Sebastian Wolf's avatar
Sebastian Wolf committed
234 235 236 237
		
		
		
		/**
238 239
		 * @brief Removes all erased nodes from the TensorNetwork. 
		 * @details The order of the node ids is retained, but the ids might decrease due to removed nodes. 
Sebastian Wolf's avatar
Sebastian Wolf committed
240 241
		 */
		void sanitize();
Baum's avatar
Baum committed
242

Sebastian Wolf's avatar
Sebastian Wolf committed
243
		
244 245 246 247 248 249
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Standard operators - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
		
		///@brief TensorNetworks are copy assignable.
		TensorNetwork& operator=(const TensorNetwork &_cpy) = default;
			
		///@brief TensorNetworks are move assignable.
Sebastian Wolf's avatar
Sebastian Wolf committed
250
		TensorNetwork& operator=(TensorNetwork &&_mv) = default;
251
		
Sebastian Wolf's avatar
Sebastian Wolf committed
252
		
Sebastian Wolf's avatar
Sebastian Wolf committed
253 254
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Conversions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
		
Sebastian Wolf's avatar
Sebastian Wolf committed
255
		/** 
256 257 258
		* @brief Explicit cast to Tensor.
		* @details Contracts the complete network into a single Tensor
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
259 260
		explicit operator Tensor() const;
		
261 262
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Access - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
		/** 
263 264
		* @brief Read the value at a specific position.
		* @details This allows the efficent calculation of a single entry of the TensorNetwork, by first fixing the external dimensions
Sebastian Wolf's avatar
Sebastian Wolf committed
265
		* and then completly contracting the network. Do NOT use this as a manual cast to Tensor (there is an explicit cast for that).
266 267 268
		* @param _position the position of the entry to be read assuming row-major ordering and a single node.
		* @returns the calculated value (NO reference)
		*/
269 270
		value_t operator[](const size_t _position) const;
		
Sebastian Wolf's avatar
Sebastian Wolf committed
271
		
272 273 274
		/** 
		* @brief Read the value at a specific position.
		* @details This allows the efficent calculation of a single entry of the TensorNetwork, by first fixing the external dimensions
Sebastian Wolf's avatar
Sebastian Wolf committed
275
		* and then completly contracting the network. Do NOT use this as a manual cast to Tensor (there is an explicit cast for that).
276 277 278
		* @param _position the position of the entry to be read assuming a single node.
		* @returns the calculated value (NO reference)
		*/
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
		value_t operator[](const std::vector<size_t>& _positions) const;
		
		
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Basic arithmetics - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
	
		/** 
		* @brief Performs the entrywise multiplication with a constant @a _factor.
		* @details Internally this only results in a change in the global factor.
		* @param _factor the factor,
		* @return a reference to this TensorNetwork.
		*/
		virtual void operator*=(const value_t _factor);
		
		
		/** 
		* @brief Performs the entrywise divison by a constant @a _divisor.
		* @details Internally this only results in a change in the global factor.
		* @param _divisor the divisor,
		* @return a reference to this TensorNetwork.
		*/ 
		virtual void operator/=(const value_t _divisor);
		
		
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Indexing - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
		/** 
		* @brief Indexes the TensorNetwork for read/write use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Baum's avatar
Baum committed
308
		template<typename... args>
Sebastian Wolf's avatar
Sebastian Wolf committed
309 310
		internal::IndexedTensor<TensorNetwork> operator()(args... _args) {
			return internal::IndexedTensor<TensorNetwork>(this, std::vector<Index>({_args...}), false);
Baum's avatar
Baum committed
311 312
		}
		
Sebastian Wolf's avatar
Sebastian Wolf committed
313
		
314
		/** 
315 316 317 318
		* @brief Indexes the TensorNetwork for read only use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Baum's avatar
Baum committed
319
		template<typename... args>
Sebastian Wolf's avatar
Sebastian Wolf committed
320 321
		internal::IndexedTensorReadOnly<TensorNetwork> operator()(args... _args) const {
			return internal::IndexedTensorReadOnly<TensorNetwork>(this, std::vector<Index>({_args...}));
Baum's avatar
Baum committed
322 323
		}
		
Sebastian Wolf's avatar
Sebastian Wolf committed
324
		
325
		/** 
326 327 328 329
		* @brief Indexes the TensorNetwork for read/write use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
330
		internal::IndexedTensor<TensorNetwork> operator()(const std::vector<Index> & _indices);
331
		
Sebastian Wolf's avatar
Sebastian Wolf committed
332
		
333 334 335 336 337
		/** 
		* @brief Indexes the TensorNetwork for read/write use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
338
		internal::IndexedTensor<TensorNetwork> operator()(      std::vector<Index>&& _indices);
Sebastian Wolf's avatar
Sebastian Wolf committed
339 340
		
		
341 342 343 344 345
		/** 
		* @brief Indexes the TensorNetwork for read only use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
346
		internal::IndexedTensorReadOnly<TensorNetwork> operator()(const std::vector<Index> & _indices) const;
347
		
Sebastian Wolf's avatar
Sebastian Wolf committed
348
		
349 350 351 352 353
		/** 
		* @brief Indexes the TensorNetwork for read only use.
		* @param _args several [indices](@ref Index) determining the desired index order.
		* @return an internal representation of an IndexedTensor(Network).
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
354
		internal::IndexedTensorReadOnly<TensorNetwork> operator()(      std::vector<Index>&& _indices) const;
Sebastian Wolf's avatar
Sebastian Wolf committed
355 356
		
		
Baum's avatar
Baum committed
357
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Operator specializations - - - - - - - - - - - - - - - - - - - - - - - - - - */
358 359
		
		///@brief (Internal) Calculates the contraction between _me and _other and stores the result in _out. Requires that *this is the tensorObjectReadOnly of _me.
Sebastian Wolf's avatar
Sebastian Wolf committed
360
		virtual bool specialized_contraction(std::unique_ptr<internal::IndexedTensorMoveable<TensorNetwork>>& _out, internal::IndexedTensorReadOnly<TensorNetwork>&& _me, internal::IndexedTensorReadOnly<TensorNetwork>&& _other) const;
361
		
Sebastian Wolf's avatar
Sebastian Wolf committed
362
		
363
		///@brief (Internal) Calculates the sum between _me and _other and stores the result in _out. Requires that *this is the tensorObjectReadOnly of _me.
Sebastian Wolf's avatar
Sebastian Wolf committed
364
		virtual bool specialized_sum(std::unique_ptr<internal::IndexedTensorMoveable<TensorNetwork>>& _out, internal::IndexedTensorReadOnly<TensorNetwork>&& _me, internal::IndexedTensorReadOnly<TensorNetwork>&& _other) const;
365
		
Sebastian Wolf's avatar
Sebastian Wolf committed
366
		
367
		///@brief (Internal) Evaluates _other into _me. Requires that *this is the tensorObjectReadOnly of _me.
Sebastian Wolf's avatar
Sebastian Wolf committed
368
		virtual void specialized_evaluation(internal::IndexedTensorWritable<TensorNetwork>&& _me, internal::IndexedTensorReadOnly<TensorNetwork>&& _other);
369 370 371 372 373 374 375 376 377 378 379
			
		/*- - - - - - - - - - - - - - - - - - - - - - - - - - Miscellaneous - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
	
		/** 
		* @brief Gets the degree of the TensorNetwork.
		* @details The degree is defined as the number of dimensions (i.e. dimensions.size()) 
		* and is always equal to the number of externalLinks (i.e. externalLinks.size()).
		* @return the degree.
		*/
		size_t degree() const;
		
380 381 382 383 384 385
		/** 
		* @brief Calculates the storage requirement of the current representation.
		* @return The datasize in sizeof(value_t).
		*/
		size_t datasize() const;
		
Sebastian Wolf's avatar
Sebastian Wolf committed
386
		
387
		/// @brief reshuffled the nodes according to the given function
388
		void reshuffle_nodes(const std::function<size_t(size_t)>& _f);
389
		
Sebastian Wolf's avatar
Sebastian Wolf committed
390
		
391
		/** 
392 393 394 395 396 397
		* @brief Sanity checks the network.
		* @details Checks whether all links in the network are set consistently and matching the 
		* underlying tensor objects. If not an exception is throws and the function does not return. 
		* Note that this only checks whether the TensorNetwork is valid not whether the additional
		* constrains of a specific format are fullfilled. For this purpose use is_in_expected_format(). 
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
398
		void require_valid_network(const bool _check_erased = true) const;
399
		
Sebastian Wolf's avatar
Sebastian Wolf committed
400
		
401
		/** 
402 403 404 405 406 407 408
		 * @brief Sanity check for the TensorNetwork and if applicable for the specific format.
		 * @details Checks whether all links in the network are set consistently and matching the 
		 * underlying tensor objects. This also checks whether the additional constrains of the specific 
		 * format (if any) are fullfilled.
		 * @return TRUE if the sanity check passes. If not an exception is thrown.
		 */
		virtual void require_correct_format() const;
409 410 411 412 413 414 415 416
		
		
		/** 
		* @brief Swaps the external indices @a _i and @a _j, effectively changing those indices for the
		* represented Tensor (e.g. a transposition for matrices).
		*/
		void swap_external_links(const size_t _i, const size_t _j);
		
Sebastian Wolf's avatar
Sebastian Wolf committed
417
		
418 419 420
		/** 
		* @brief Inserts all nodes from @a _toInsert into @a _base, creating links where demanded by the indices.
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
421
		static void add_network_to_network(internal::IndexedTensorWritable<TensorNetwork>&& _base, internal::IndexedTensorReadOnly<TensorNetwork>&& _toInsert);
422
		
Sebastian Wolf's avatar
Sebastian Wolf committed
423
		
424
		/** 
425
		 * @brief Finds traces defined by the indices and internally links the corresponding indices. Also applys all fixed indices
426 427
		 * @details For each trace this reduces the degree of the TN by two and removes two indices from the IndexedTensor.
		 */
428 429
		static void link_traces_and_fix(internal::IndexedTensorWritable<TensorNetwork>&& _base);
		
430
		
Fuchsi*'s avatar
Fuchsi* committed
431
		
432
	public:
433
		/**
434 435 436 437
		* @brief Thresholds the rank between two given nodes.
		* @details The given nodes must be joined by a single edge. Both nodes are contracted and an SVD is calculated to perform the thresholding.
		* The obtained core is contracted to nodeB, i.e. nodeA remains orthogonal in the used matrification.
		* @param _nodeA First node that takes part in the rank thresholding. This node remains orthogonalized.
438
		* @param _nodeB Second node that takes part in the rank thresholding. This nodes carries the core afterwards.
439 440 441 442
		* @param _maxRank Maximal allowed rank.
		* @param _eps Epsilion to be used in the SVD to determine zero singular values.
		* @param _softThreshold Softthreshold that is to be applied.
		*/
Fuchsi*'s avatar
Fuchsi* committed
443
		virtual void round_edge(const size_t _nodeA, const size_t _nodeB, const size_t _maxRank, const double _eps, const double _softThreshold);
444
		
Sebastian Wolf's avatar
Sebastian Wolf committed
445
		
446
		/**
447 448
		* @brief Transfers the core from one given node to another.
		* @details The given nodes must be joined by a single edge. A QR decomposition of the first node is calculated and the core contracted to the second one.
449 450
		* @param _from First node, which remains orthogonalized.
		* @param _to Second node, which carries the core afterwards.
451 452
		* @param _allowRankReduction Flag indicating whether a rank revealing decomposition is to be used which allows the reduction of the rank.
		*/
453
		virtual void transfer_core(const size_t _from, const size_t _to, const bool _allowRankReduction = true);
Sebastian Wolf's avatar
Sebastian Wolf committed
454
		
Sebastian Wolf's avatar
Sebastian Wolf committed
455
		
456
		/**
Sebastian Wolf's avatar
Sebastian Wolf committed
457
		* @brief Contracts all nodes that are joined by a full-rank edge.
458 459
		* @details This reduces the overall storage requirements and can be useful to store intermediate results e.g. after fixing one of several indices.
		*/
460 461
		void reduce_representation();
		
Sebastian Wolf's avatar
Sebastian Wolf committed
462
		
Sebastian Wolf's avatar
Sebastian Wolf committed
463
		/** 
464 465 466
		* @brief Fixes a specific mode to a specific value, effectively reducing the order by one.
		* @param _mode the mode in which the slate shall be fixed, e.g. 0 to fix the first mode.
		* @param _slatePosition the position in the corresponding mode that shall be used.
467
		*/
468 469 470 471 472 473
		virtual void fix_mode(const size_t _mode, const size_t _slatePosition);
		
		__attribute__((deprecated("function has been renamed. please use 'fix_mode'"))) 
		void fix_slate(const size_t _dimPos, const size_t _slatePosition) {
			fix_mode(_dimPos, _slatePosition);
		}
Sebastian Wolf's avatar
Sebastian Wolf committed
474
		
475
		/**
476
		 * @brief removes the given @a _slatePosition from the @a _mode. this reduces the given dimension by one
477
		 */
478
		virtual void remove_slate(const size_t _mode, const size_t _slatePosition);
Sebastian Wolf's avatar
Sebastian Wolf committed
479
		
480
		/** 
481 482 483 484
		 * @brief Resizes a specific mode of the TensorNetwork.
		 * @param _mode the mode to resize.
		 * @param _newDim the new value that resized mode shall have.
		 * @param _cutPos the position within the selected mode in front of which slates are inserted 
485 486 487
		 * or removed. By default the current dimension, i.e new slates are added after the last current one
		 * and removed starting from the last one.
		 */
488
		virtual void resize_mode(const size_t _mode, const size_t _newDim, const size_t _cutPos=~0ul);
489
		
490 491 492 493
		__attribute__((deprecated("function has been renamed. please use 'resize_mode'"))) 
		void resize_dimension(const size_t _mode, const size_t _newDim, const size_t _cutPos=~0ul) {
			resize_mode(_mode, _newDim, _cutPos);
		}
494
		
Baum's avatar
Baum committed
495
		/**
Sebastian Wolf's avatar
Sebastian Wolf committed
496 497 498 499
		 * @brief Contracts the nodes with indices @a _nodeId1 and @a _nodeId2.
		 * @details Replaces @a _nodeId1 with the contraction and erases @a _nodeId2.
		 * @param _nodeId1 The first node, that will contain the result afterwards.
		 * @param _nodeId2 The second node, that will be erased afterwards.
Baum's avatar
Baum committed
500
		*/
Sebastian Wolf's avatar
Sebastian Wolf committed
501
		void contract(const size_t _nodeId1, const size_t _nodeId2);
Baum's avatar
Baum committed
502
		
Sebastian Wolf's avatar
Sebastian Wolf committed
503
		
504
		/** 
505 506 507 508 509 510
		* @brief Approximates the cost of contraction two given nodes.
		* @param _nodeId1 id of the first node.
		* @param _nodeId2 id of the second node.
		* @return The approxiamted contraction cost.
		*/
		double contraction_cost(const size_t _nodeId1, const size_t _nodeId2) const;
Baum's avatar
Baum committed
511
		
Sebastian Wolf's avatar
Sebastian Wolf committed
512
		
Baum's avatar
Baum committed
513
		/**
Sebastian Wolf's avatar
Sebastian Wolf committed
514 515 516 517 518
		 * @brief Contracts the nodes with with indices included in the given set @a _ids.
		 * @details Erases all nodes but one, which id is returned.
		 * @param _ids set with all ids to be erased.
		 * @return The id in which the result of the contraction is stored.
		 */
519
		size_t contract(const std::set<size_t>& _ids);
Baum's avatar
Baum committed
520
		
Sebastian Wolf's avatar
Sebastian Wolf committed
521
		
522
		/** 
523 524 525
		* @brief Calculates the frobenious norm of the TensorNetwork.
		* @return the frobenious norm of the TensorNetwork.
		*/
Baum's avatar
Baum committed
526
		virtual value_t frob_norm() const;
527
		
528
		
529
		/**
530 531 532 533
		* @brief Draws a graph representation of the TensorNetwork.
		* @details The drawing is realized by a system call to "dot" which plots the graph structure.
		* @param _filename path and name of the file where to save the image.
		*/
534
		void draw(const std::string& _filename) const;
535
	};
536
	
537
	TensorNetwork operator*(TensorNetwork &_lhs, value_t _factor);
538
	
539 540 541
	TensorNetwork operator*(value_t _factor, TensorNetwork &_rhs);
	
	TensorNetwork operator/(TensorNetwork &_lhs, value_t _factor);
542
	
543 544 545 546 547
	/** 
	* @brief Calculates the frobenious norm of the given TensorNetwork.
	* @param _network the TensorNetwork of which the frobenious norm shall be calculated.
	* @return the frobenious norm.
	*/
548
	static XERUS_force_inline value_t frob_norm(const TensorNetwork& _network) { return _network.frob_norm(); }
549
	
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
	
	/** 
	* @brief Checks whether two TensorNetworks are approximately equal.
	* @details Check whether ||@a _a - @a _b ||/(||@a a ||/2 + ||@a _b ||/2) < @a _eps, i.e. whether the relative difference in the frobenius norm is sufficently small.
	* @param _a the first test candidate.
	* @param _b the second test candidate
	* @param _eps the maximal relative difference between @a _a and @a _b.
	* @return TRUE if @a _a and @a _b are determined to be approximately equal, FALSE otherwise.
	*/
	bool approx_equal(const TensorNetwork& _a, const TensorNetwork& _b, const value_t _eps = EPSILON);
	
	
	/** 
	* @brief Convinience wrapper, casts the the given TensorNetwork @a _a to Tensor and calls the Tensor function.
	*/
	bool approx_equal(const TensorNetwork& _a, const Tensor& _b, const value_t _eps = EPSILON);
	
	
	/** 
	* @brief Convinience wrapper, casts the the given TensorNetwork @a _b to Tensor and calls the Tensor function.
	*/
	bool approx_equal(const Tensor& _a, const TensorNetwork& _b, const value_t _eps = EPSILON);
	
	
574
	std::ostream &operator<<(std::ostream &_out, const TensorNetwork::Link &_rhs);
575 576 577 578 579 580
	
	namespace misc {
		/**
		* @brief Pipes all information necessary to restore the current TensorNetwork into @a _stream.
		* @note that this excludes header information
		*/
581
		void stream_writer(std::ostream &_stream, const TensorNetwork &_obj, const FileFormat _format);
582 583 584 585
		
		/**
		* @brief Restores the TensorNetwork from a stream of data. 
		*/
586
		void stream_reader(std::istream &_stream, TensorNetwork &_obj, const FileFormat _format);
587
	}
Baum's avatar
Baum committed
588
}