diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2573642..4601762 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: jobs: - tests: + tests_basics: runs-on: ubuntu-latest @@ -33,6 +33,21 @@ jobs: - name: Test decompositions if: always() run: pytest tests/decompositions/test_svd_decompositions.py --cov=tensorkrowch + + tests_models: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install dependencies + run: python -m pip install --upgrade pip torch opt_einsum + - name: Install pytest + run: pip install pytest pytest-cov - name: Test MPS if: always() run: pytest tests/models/test_mps.py --cov=tensorkrowch @@ -44,4 +59,4 @@ jobs: run: pytest tests/models/test_peps.py --cov=tensorkrowch - name: Test Tree if: always() - run: pytest tests/models/test_tree.py --cov=tensorkrowch + run: pytest tests/models/test_tree.py --cov=tensorkrow \ No newline at end of file diff --git a/docs/_build/doctest/output.txt b/docs/_build/doctest/output.txt index 1b925f4..ecdef6d 100644 --- a/docs/_build/doctest/output.txt +++ b/docs/_build/doctest/output.txt @@ -1,22 +1,6 @@ -Results of doctest builder run on 2024-05-13 15:19:16 +Results of doctest builder run on 2024-05-14 21:33:03 ===================================================== -Document: models ----------------- -1 items passed all tests: - 118 tests in default -118 tests in 1 items. -118 passed and 0 failed. -Test passed. - -Document: embeddings --------------------- -1 items passed all tests: - 45 tests in default -45 tests in 1 items. -45 passed and 0 failed. -Test passed. - Document: components -------------------- ********************************************************************** @@ -27,8 +11,8 @@ Expected: tensor([[-0.2799, -0.4383, -0.8387], [ 1.6225, -0.3370, -1.2316]]) Got: - tensor([[-0.3491, 1.6723, 0.1550], - [-1.2811, 1.7880, 1.4058]]) + tensor([[-1.0631, -0.4740, 0.1857], + [ 0.1684, 0.9431, -0.5282]]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -36,7 +20,7 @@ Failed example: Expected: tensor(-1.5029) Got: - tensor(3.3910) + tensor(-0.7681) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -44,7 +28,7 @@ Failed example: Expected: tensor([ 1.3427, -0.7752, -2.0704]) Got: - tensor([-1.6301, 3.4603, 1.5608]) + tensor([-0.8947, 0.4691, -0.3424]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -53,8 +37,8 @@ Expected: tensor([[ 1.4005, -0.0521, -1.2091], [ 1.9844, 0.3513, -0.5920]]) Got: - tensor([[ 0.1392, -1.0223, -1.4595], - [-0.8048, 0.5959, -0.3506]]) + tensor([[ 0.7595, 0.6039, -0.3528], + [-0.9391, 0.5732, -0.1683]]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -62,7 +46,7 @@ Failed example: Expected: tensor(0.3139) Got: - tensor(-0.4837) + tensor(0.0794) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -70,7 +54,7 @@ Failed example: Expected: tensor([ 1.6925, 0.1496, -0.9006]) Got: - tensor([-0.3328, -0.2132, -0.9050]) + tensor([-0.0898, 0.5886, -0.2606]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -79,8 +63,8 @@ Expected: tensor([[ 0.2111, -0.9551, -0.7812], [ 0.2254, 0.3381, -0.2461]]) Got: - tensor([[-1.0223, -0.8771, -2.0712], - [-0.8749, -0.0445, 0.0772]]) + tensor([[-0.5163, -1.9652, 0.5784], + [ 1.1581, 1.1339, -0.2820]]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -88,7 +72,7 @@ Failed example: Expected: tensor(0.5567) Got: - tensor(0.7768) + tensor(1.1973) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -96,7 +80,7 @@ Failed example: Expected: tensor([0.0101, 0.9145, 0.3784]) Got: - tensor([0.1042, 0.5887, 1.5192]) + tensor([1.1840, 2.1914, 0.6084]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -105,8 +89,8 @@ Expected: tensor([[ 1.5570, 1.8441, -0.0743], [ 0.4572, 0.7592, 0.6356]]) Got: - tensor([[-0.5176, -0.2405, -0.4334], - [-0.5865, -0.3753, 0.4047]]) + tensor([[ 0.4585, -0.9622, -1.3563], + [ 1.5910, -1.6511, 1.4884]]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -114,7 +98,7 @@ Failed example: Expected: tensor(2.6495) Got: - tensor(1.0781) + tensor(3.2324) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -122,7 +106,7 @@ Failed example: Expected: tensor([1.6227, 1.9942, 0.6399]) Got: - tensor([0.7822, 0.4458, 0.5930]) + tensor([1.6557, 1.9110, 2.0137]) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -153,17 +137,17 @@ Got: Node( name: my_node tensor: - tensor([[[-0.6988, -1.1643], - [-0.4288, 1.4445], - [ 0.3650, 0.1796], - [-0.7360, -0.4975], - [ 0.2338, -0.2614]], + tensor([[[ 0.0756, 0.2978], + [-0.9519, -0.6720], + [-0.5188, -0.1702], + [-0.5977, 0.7331], + [ 0.2803, -0.6546]], - [[ 1.4763, -0.5471], - [ 0.1191, 0.6986], - [ 0.4719, 0.6936], - [-0.3989, -0.9837], - [-0.7574, -0.4083]]]) + [[ 0.1922, -1.1753], + [ 0.1176, 0.1418], + [ 0.3928, 0.8509], + [-0.5760, 0.9210], + [ 2.1306, -1.1455]]]) axes: [left input @@ -202,17 +186,17 @@ Got: Node( name: node tensor: - tensor([[[ 5.5549e-01, -7.1141e-01], - [ 1.3587e-02, -7.7982e-01], - [-2.4167e-01, 3.1204e-01], - [ 1.2386e-03, -4.0765e-02], - [ 1.2701e-01, -1.3453e-01]], + tensor([[[ 1.0910, -0.5809], + [ 0.1853, 0.3664], + [-0.0117, 0.5005], + [-0.0661, 0.0234], + [-0.8290, 1.9922]], - [[-1.8415e+00, 3.0231e-01], - [-1.0302e+00, 1.9352e+00], - [-2.3677e+00, 9.1492e-01], - [ 1.0165e+00, -4.1301e-01], - [-1.0887e+00, 2.1221e-01]]]) + [[ 0.1525, 0.9578], + [ 0.7693, 0.5078], + [ 0.1810, -1.0350], + [ 0.3174, -0.2801], + [ 0.4202, -0.4585]]]) axes: [axis_0 axis_1 @@ -264,17 +248,17 @@ Got: name: my_paramnode tensor: Parameter containing: - tensor([[[-0.7826, 0.0821], - [ 0.3175, 0.7941], - [ 1.5045, -0.8090], - [ 0.3632, -0.3924], - [ 1.7720, 2.3521]], + tensor([[[ 0.7591, 0.2141], + [ 0.4399, -2.5171], + [-3.7951, 0.2628], + [-0.2629, 2.4291], + [ 1.8276, 0.2167]], - [[ 0.7189, 0.9170], - [ 0.0166, 0.3871], - [ 1.1382, -1.4283], - [-0.7954, 0.0954], - [-0.3044, 0.9413]]], requires_grad=True) + [[-0.4733, 1.6149], + [ 0.0621, 0.6297], + [ 0.4117, 0.4973], + [-0.1463, -0.2648], + [-1.0274, -1.1514]]], requires_grad=True) axes: [left input @@ -315,17 +299,17 @@ Got: name: paramnode tensor: Parameter containing: - tensor([[[-0.2850, -0.0664], - [-0.2535, 1.0285], - [-0.4207, 0.8395], - [-0.7933, 0.1413], - [-1.4896, -0.7656]], + tensor([[[-1.3839, -1.1648], + [-0.2835, -0.6608], + [ 0.1896, -0.8977], + [-1.0581, 0.9863], + [-1.2442, -0.7461]], - [[-0.4232, 0.1107], - [-0.5041, -1.5471], - [ 0.6676, 1.5313], - [ 1.4140, -1.2289], - [ 1.2960, -1.4492]]], requires_grad=True) + [[ 0.2663, -0.2669], + [-0.9733, 1.0781], + [ 0.2842, -0.3121], + [-0.9311, -0.5546], + [ 0.4118, 1.2157]]], requires_grad=True) axes: [axis_0 axis_1 @@ -344,8 +328,8 @@ Expected: [ 1.3371, 1.4761, 0.6551]], requires_grad=True) Got: Parameter containing: - tensor([[ 0.5249, 0.1834, 1.2888], - [-0.4819, 0.8874, 0.0728]], requires_grad=True) + tensor([[-0.4446, 0.2519, 1.6840], + [ 1.2981, -0.4704, -0.1416]], requires_grad=True) ********************************************************************** File "../tensorkrowch/components.py", line ?, in default Failed example: @@ -396,11 +380,19 @@ Got: data_0[feature] <-> nodeA[input]]) ********************************************************************** 1 items had failures: - 21 of 398 in default -398 tests in 1 items. -377 passed and 21 failed. + 21 of 401 in default +401 tests in 1 items. +380 passed and 21 failed. ***Test Failed*** 21 failures. +Document: embeddings +-------------------- +1 items passed all tests: + 45 tests in default +45 tests in 1 items. +45 passed and 0 failed. +Test passed. + Document: operations -------------------- 1 items passed all tests: @@ -409,9 +401,17 @@ Document: operations 214 passed and 0 failed. Test passed. +Document: models +---------------- +1 items passed all tests: + 118 tests in default +118 tests in 1 items. +118 passed and 0 failed. +Test passed. + Doctest summary =============== - 775 tests + 778 tests 21 failures in tests 0 failures in setup code 0 failures in cleanup code diff --git a/docs/_build/doctrees/components.doctree b/docs/_build/doctrees/components.doctree index 2d1dbe4..1583617 100644 Binary files a/docs/_build/doctrees/components.doctree and b/docs/_build/doctrees/components.doctree differ diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index a7f1663..7de6fb4 100644 Binary files a/docs/_build/doctrees/environment.pickle and b/docs/_build/doctrees/environment.pickle differ diff --git a/docs/_build/doctrees/models.doctree b/docs/_build/doctrees/models.doctree index eb19824..3e21eec 100644 Binary files a/docs/_build/doctrees/models.doctree and b/docs/_build/doctrees/models.doctree differ diff --git a/docs/_build/doctrees/tutorials/0_first_steps.doctree b/docs/_build/doctrees/tutorials/0_first_steps.doctree index 92aae46..aabdd71 100644 Binary files a/docs/_build/doctrees/tutorials/0_first_steps.doctree and b/docs/_build/doctrees/tutorials/0_first_steps.doctree differ diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo index 218778c..38ea4b1 100644 --- a/docs/_build/html/.buildinfo +++ b/docs/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: e4485bdccc4a9ef1ab7141439481b17d +config: c711dcb750f5eb023ece44b19b251e46 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_build/html/_modules/index.html b/docs/_build/html/_modules/index.html index b16a90d..4c08981 100644 --- a/docs/_build/html/_modules/index.html +++ b/docs/_build/html/_modules/index.html @@ -5,7 +5,7 @@
-
node1_list: Optional[List[bool]] = None,
init_method: Optional[Text] = None,
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
super().__init__()
@@ -888,7 +889,10 @@ Source code for tensorkrowch.components
if shape is not None:
if init_method is not None:
self._unrestricted_set_tensor(
- init_method=init_method, device=device, **kwargs)
+ init_method=init_method,
+ device=device,
+ dtype=dtype,
+ **kwargs)
else:
self._unrestricted_set_tensor(tensor=tensor)
@@ -1096,6 +1100,36 @@ Source code for tensorkrowch.components
their own tensors or use other node's tensor.
"""
return not (self._leaf or self._data or self._virtual)
+
+[docs] def is_conj(self) -> bool:
+ """
+ Equivalent to `torch.is_conj()
+ <https://pytorch.org/docs/stable/generated/torch.is_conj.html>`_.
+ """
+ tensor = self.tensor
+ if tensor is None:
+ return
+ return tensor.is_conj()
+
+[docs] def is_complex(self) -> bool:
+ """
+ Equivalent to `torch.is_complex()
+ <https://pytorch.org/docs/stable/generated/torch.is_complex.html>`_.
+ """
+ tensor = self.tensor
+ if tensor is None:
+ return
+ return tensor.is_complex()
+
+[docs] def is_floating_point(self) -> bool:
+ """
+ Equivalent to `torch.is_floating_point()
+ <https://pytorch.org/docs/stable/generated/torch.is_floating_point.html>`_.
+ """
+ tensor = self.tensor
+ if tensor is None:
+ return
+ return tensor.is_floating_point()
[docs] def size(self, axis: Optional[Ax] = None) -> Union[Size, int]:
"""
@@ -1497,9 +1531,10 @@ Source code for tensorkrowch.components
@staticmethod
def _make_copy_tensor(shape: Shape,
- device: torch.device = torch.device('cpu')) -> Tensor:
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> Tensor:
"""Returns copy tensor (ones in the "diagonal", zeros elsewhere)."""
- copy_tensor = torch.zeros(shape, device=device)
+ copy_tensor = torch.zeros(shape, device=device, dtype=dtype)
rank = len(shape)
if rank <= 1:
i = 0
@@ -1512,7 +1547,8 @@ Source code for tensorkrowch.components
def _make_rand_tensor(shape: Shape,
low: float = 0.,
high: float = 1.,
- device: torch.device = torch.device('cpu')) -> Tensor:
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> Tensor:
"""Returns tensor whose entries are drawn from the uniform distribution."""
if not isinstance(low, float):
raise TypeError('`low` should be float type')
@@ -1520,13 +1556,14 @@ Source code for tensorkrowch.components
raise TypeError('`high` should be float type')
if low >= high:
raise ValueError('`low` should be strictly smaller than `high`')
- return torch.rand(shape, device=device) * (high - low) + low
+ return torch.rand(shape, device=device, dtype=dtype) * (high - low) + low
@staticmethod
def _make_randn_tensor(shape: Shape,
mean: float = 0.,
std: float = 1.,
- device: torch.device = torch.device('cpu')) -> Tensor:
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> Tensor:
"""Returns tensor whose entries are drawn from the normal distribution."""
if not isinstance(mean, float):
raise TypeError('`mean` should be float type')
@@ -1534,12 +1571,13 @@ Source code for tensorkrowch.components
raise TypeError('`std` should be float type')
if std <= 0:
raise ValueError('`std` should be positive')
- return torch.randn(shape, device=device) * std + mean
+ return torch.randn(shape, device=device, dtype=dtype) * std + mean
[docs] def make_tensor(self,
shape: Optional[Shape] = None,
init_method: Text = 'zeros',
- device: torch.device = torch.device('cpu'),
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> Tensor:
"""
Returns a tensor that can be put in the node, and is initialized according
@@ -1553,6 +1591,8 @@ Source code for tensorkrowch.components
Initialization method.
device : torch.device, optional
Device where to initialize the tensor.
+ dtype : torch.dtype, optional
+ Dtype of the tensor.
kwargs : float
Keyword arguments for the different initialization methods:
@@ -1574,15 +1614,17 @@ Source code for tensorkrowch.components
if shape is None:
shape = self._shape
if init_method == 'zeros':
- return torch.zeros(shape, device=device)
+ return torch.zeros(shape, device=device, dtype=dtype)
elif init_method == 'ones':
- return torch.ones(shape, device=device)
+ return torch.ones(shape, device=device, dtype=dtype)
elif init_method == 'copy':
- return self._make_copy_tensor(shape, device=device)
+ return self._make_copy_tensor(shape, device=device, dtype=dtype)
elif init_method == 'rand':
- return self._make_rand_tensor(shape, device=device, **kwargs)
+ return self._make_rand_tensor(shape, device=device, dtype=dtype,
+ **kwargs)
elif init_method == 'randn':
- return self._make_randn_tensor(shape, device=device, **kwargs)
+ return self._make_randn_tensor(shape, device=device, dtype=dtype,
+ **kwargs)
else:
raise ValueError('Choose a valid `init_method`: "zeros", '
'"ones", "copy", "rand", "randn"')
@@ -1655,6 +1697,7 @@ Source code for tensorkrowch.components
tensor: Optional[Tensor] = None,
init_method: Optional[Text] = 'zeros',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Sets a new node's tensor or creates one with :meth:`make_tensor` and sets
@@ -1673,6 +1716,8 @@ Source code for tensorkrowch.components
Initialization method.
device : torch.device, optional
Device where to initialize the tensor.
+ dtype : torch.dtype, optional
+ Dtype of the tensor.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`make_tensor`.
@@ -1680,10 +1725,14 @@ Source code for tensorkrowch.components
if tensor is not None:
if not isinstance(tensor, Tensor):
raise TypeError('`tensor` should be torch.Tensor type')
- elif device is not None:
+ if device is not None:
warnings.warn('`device` was specified but is being ignored. '
'Provide a tensor that is already in the required'
' device')
+ if dtype is not None:
+ warnings.warn('`dtype` was specified but is being ignored. '
+ 'Provide a tensor that already has the required'
+ ' dtype')
if not self._compatible_shape(tensor):
tensor = self._crop_tensor(tensor)
@@ -1691,10 +1740,13 @@ Source code for tensorkrowch.components
elif init_method is not None:
node_tensor = self.tensor
- if (device is None) and (node_tensor is not None):
- device = node_tensor.device
+ if node_tensor is not None:
+ if device is None:
+ device = node_tensor.device
+ if dtype is None:
+ dtype = node_tensor.dtype
tensor = self.make_tensor(
- init_method=init_method, device=device, **kwargs)
+ init_method=init_method, device=device, dtype=dtype, **kwargs)
correct_format_tensor = self._set_tensor_format(tensor)
else:
@@ -1707,6 +1759,7 @@ Source code for tensorkrowch.components
tensor: Optional[Tensor] = None,
init_method: Optional[Text] = 'zeros',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Sets new node's tensor or creates one with :meth:`make_tensor` and sets
@@ -1740,6 +1793,8 @@ Source code for tensorkrowch.components
Initialization method.
device : torch.device, optional
Device where to initialize the tensor.
+ dtype : torch.dtype, optional
+ Dtype of the tensor.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`make_tensor`.
@@ -1780,6 +1835,7 @@ Source code for tensorkrowch.components
self._unrestricted_set_tensor(tensor=tensor,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
else:
raise ValueError('Node\'s tensor can only be changed if it is not'
@@ -2332,6 +2388,8 @@ Source code for tensorkrowch.components
Initialization method.
device : torch.device, optional
Device where to initialize the tensor if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`AbstractNode.make_tensor`.
@@ -2656,6 +2714,8 @@ Source code for tensorkrowch.components
Initialization method.
device : torch.device, optional
Device where to initialize the tensor if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`AbstractNode.make_tensor`.
@@ -2737,6 +2797,7 @@ Source code for tensorkrowch.components
node1_list: Optional[List[bool]] = None,
init_method: Optional[Text] = None,
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
super().__init__(shape=shape,
@@ -2752,6 +2813,7 @@ Source code for tensorkrowch.components
node1_list=node1_list,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
# ----------
diff --git a/docs/_build/html/_modules/tensorkrowch/decompositions/svd_decompositions.html b/docs/_build/html/_modules/tensorkrowch/decompositions/svd_decompositions.html
index dfab7d8..faa1d44 100644
--- a/docs/_build/html/_modules/tensorkrowch/decompositions/svd_decompositions.html
+++ b/docs/_build/html/_modules/tensorkrowch/decompositions/svd_decompositions.html
@@ -5,7 +5,7 @@
- tensorkrowch.decompositions.svd_decompositions — TensorKrowch 1.1.2 documentation
+ tensorkrowch.decompositions.svd_decompositions — TensorKrowch 1.1.3 documentation
@@ -472,6 +472,9 @@ Source code for tensorkrowch.decompositions.svd_decompositions
tensors.append(u)
prev_bond = aux_rank
+
+ if vh.is_complex():
+ s = s.to(vh.dtype)
vec = torch.diag_embed(s) @ vh
tensors.append(vec)
@@ -608,6 +611,9 @@ Source code for tensorkrowch.decompositions.svd_decompositions
tensors.append(u)
prev_bond = aux_rank
+
+ if vh.is_complex():
+ s = s.to(vh.dtype)
mat = torch.diag_embed(s) @ vh
mat = mat.reshape(aux_rank, in_out_dims[-2], in_out_dims[-1])
diff --git a/docs/_build/html/_modules/tensorkrowch/embeddings.html b/docs/_build/html/_modules/tensorkrowch/embeddings.html
index fea19d8..c21c6f0 100644
--- a/docs/_build/html/_modules/tensorkrowch/embeddings.html
+++ b/docs/_build/html/_modules/tensorkrowch/embeddings.html
@@ -5,7 +5,7 @@
- tensorkrowch.embeddings — TensorKrowch 1.1.2 documentation
+ tensorkrowch.embeddings — TensorKrowch 1.1.3 documentation
diff --git a/docs/_build/html/_modules/tensorkrowch/initializers.html b/docs/_build/html/_modules/tensorkrowch/initializers.html
index 7ae7d3d..a2bdba3 100644
--- a/docs/_build/html/_modules/tensorkrowch/initializers.html
+++ b/docs/_build/html/_modules/tensorkrowch/initializers.html
@@ -5,7 +5,7 @@
- tensorkrowch.initializers — TensorKrowch 1.1.2 documentation
+ tensorkrowch.initializers — TensorKrowch 1.1.3 documentation
diff --git a/docs/_build/html/_modules/tensorkrowch/models/mpo.html b/docs/_build/html/_modules/tensorkrowch/models/mpo.html
index 37300e8..92ac5ec 100644
--- a/docs/_build/html/_modules/tensorkrowch/models/mpo.html
+++ b/docs/_build/html/_modules/tensorkrowch/models/mpo.html
@@ -5,7 +5,7 @@
- tensorkrowch.models.mpo — TensorKrowch 1.1.2 documentation
+ tensorkrowch.models.mpo — TensorKrowch 1.1.3 documentation
@@ -408,6 +408,8 @@ Source code for tensorkrowch.models.mpo
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -448,6 +450,7 @@ Source code for tensorkrowch.models.mpo
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
super().__init__(name='mpo')
@@ -594,6 +597,7 @@ Source code for tensorkrowch.models.mpo
self.initialize(tensors=tensors,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
# ----------
@@ -726,6 +730,7 @@ Source code for tensorkrowch.models.mpo
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes all the nodes of the :class:`MPO`. It can be called when
@@ -735,7 +740,7 @@ Source code for tensorkrowch.models.mpo
* ``{"zeros", "ones", "copy", "rand", "randn"}``: Each node is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
Parameters
----------
@@ -749,6 +754,8 @@ Source code for tensorkrowch.models.mpo
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -763,6 +770,8 @@ Source code for tensorkrowch.models.mpo
if device is None:
device = tensors[0].device
+ if dtype is None:
+ dtype = tensors[0].dtype
if len(tensors) == 1:
tensors[0] = tensors[0].reshape(1,
@@ -773,13 +782,15 @@ Source code for tensorkrowch.models.mpo
else:
# Left node
aux_tensor = torch.zeros(*self._mats_env[0].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[0] = tensors[0]
tensors[0] = aux_tensor
# Right node
aux_tensor = torch.zeros(*self._mats_env[-1].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0, :] = tensors[-1]
tensors[-1] = aux_tensor
@@ -791,10 +802,13 @@ Source code for tensorkrowch.models.mpo
for i, node in enumerate(self._mats_env):
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if self._boundary == 'obc':
- aux_tensor = torch.zeros(*node.shape, device=device)
+ aux_tensor = torch.zeros(*node.shape,
+ device=device,
+ dtype=dtype)
if i == 0:
# Left node
aux_tensor[0] = node.tensor[0]
@@ -804,8 +818,12 @@ Source code for tensorkrowch.models.mpo
node.tensor = aux_tensor
if self._boundary == 'obc':
- self._left_node.set_tensor(init_method='copy', device=device)
- self._right_node.set_tensor(init_method='copy', device=device)
+ self._left_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
+ self._right_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
[docs] def set_data_nodes(self) -> None:
"""
@@ -842,7 +860,8 @@ Source code for tensorkrowch.models.mpo
tensors=None,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mpo.name = self.name + '_copy'
if share_tensors:
for new_node, node in zip(new_mpo._mats_env, self._mats_env):
@@ -1352,6 +1371,8 @@ Source code for tensorkrowch.models.mpo
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -1380,6 +1401,7 @@ Source code for tensorkrowch.models.mpo
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
tensors = None
@@ -1424,6 +1446,7 @@ Source code for tensorkrowch.models.mpo
n_batches=n_batches,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.name = 'umpo'
@@ -1449,6 +1472,7 @@ Source code for tensorkrowch.models.mpo
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes the common tensor of the :class:`UMPO`. It can be called
@@ -1458,7 +1482,7 @@ Source code for tensorkrowch.models.mpo
* ``{"zeros", "ones", "copy", "rand", "randn"}``: The tensor is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
Parameters
----------
@@ -1470,6 +1494,8 @@ Source code for tensorkrowch.models.mpo
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -1480,6 +1506,7 @@ Source code for tensorkrowch.models.mpo
elif init_method is not None:
self.uniform_memory.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
[docs] def copy(self, share_tensors: bool = False) -> 'UMPO':
@@ -1507,7 +1534,8 @@ Source code for tensorkrowch.models.mpo
tensor=None,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mpo.name = self.name + '_copy'
if share_tensors:
new_mpo.uniform_memory.tensor = self.uniform_memory.tensor
diff --git a/docs/_build/html/_modules/tensorkrowch/models/mps.html b/docs/_build/html/_modules/tensorkrowch/models/mps.html
index 563ef92..17a676b 100644
--- a/docs/_build/html/_modules/tensorkrowch/models/mps.html
+++ b/docs/_build/html/_modules/tensorkrowch/models/mps.html
@@ -5,7 +5,7 @@
- tensorkrowch.models.mps — TensorKrowch 1.1.2 documentation
+ tensorkrowch.models.mps — TensorKrowch 1.1.3 documentation
@@ -438,6 +438,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -497,6 +499,7 @@ Source code for tensorkrowch.models.mps
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
super().__init__(name='mps')
@@ -690,6 +693,7 @@ Source code for tensorkrowch.models.mps
self.initialize(tensors=tensors,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
# ----------
@@ -906,7 +910,9 @@ Source code for tensorkrowch.models.mps
if i == self._n_features - 1:
self._mats_env[-1]['right'] ^ self._right_node['left']
- def _make_canonical(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_canonical(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS in canonical form with
orthogonality center at the rightmost node. Unitaries in nodes are
@@ -934,22 +940,22 @@ Source code for tensorkrowch.models.mps
phys_dim = node_shape[1]
size = max(aux_shape[0], aux_shape[1])
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:min(aux_shape[0], size), :min(aux_shape[1], size)]
tensor = tensor.reshape(*node_shape)
if i == (self._n_features - 1):
- if self._boundary == 'obc':
- tensor = tensor.t() / tensor.norm() * sqrt(phys_dim)
- else:
- tensor = tensor / tensor.norm() * sqrt(phys_dim)
- else:
- tensor = tensor * sqrt(phys_dim)
+ if (self._boundary == 'obc') and (i == 0):
+ tensor = tensor[:, 0]
+ tensor = tensor / tensor.norm()
+ tensor = tensor * sqrt(phys_dim)
tensors.append(tensor)
return tensors
- def _make_unitaries(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_unitaries(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS nodes as stacks of
unitaries.
@@ -973,7 +979,7 @@ Source code for tensorkrowch.models.mps
size_2 = min(node.shape[2], size)
for _ in range(node.shape[1]):
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:size_1, :size_2]
units.append(tensor)
@@ -981,19 +987,18 @@ Source code for tensorkrowch.models.mps
if self._boundary == 'obc':
if i == 0:
- tensors.append(units.squeeze(0))
+ units = units.squeeze(0)
elif i == (self._n_features - 1):
- tensors.append(units.squeeze(-1))
- else:
- tensors.append(units)
- else:
- tensors.append(units)
+ units = units.squeeze(-1)
+ tensors.append(units)
+
return tensors
[docs] def initialize(self,
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes all the nodes of the :class:`MPS`. It can be called when
@@ -1003,7 +1008,7 @@ Source code for tensorkrowch.models.mps
* ``{"zeros", "ones", "copy", "rand", "randn"}``: Each node is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
* ``"randn_eye"``: Nodes are initialized as in this
`paper <https://arxiv.org/abs/1605.03795>`_, adding identities at the
@@ -1033,14 +1038,16 @@ Source code for tensorkrowch.models.mps
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
"""
if init_method == 'unit':
- tensors = self._make_unitaries(device=device)
+ tensors = self._make_unitaries(device=device, dtype=dtype)
elif init_method == 'canonical':
- tensors = self._make_canonical(device=device)
+ tensors = self._make_canonical(device=device, dtype=dtype)
if tensors is not None:
if len(tensors) != self._n_features:
@@ -1052,19 +1059,23 @@ Source code for tensorkrowch.models.mps
if device is None:
device = tensors[0].device
+ if dtype is None:
+ dtype = tensors[0].dtype
if len(tensors) == 1:
tensors[0] = tensors[0].reshape(1, -1, 1)
else:
# Left node
aux_tensor = torch.zeros(*self._mats_env[0].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[0] = tensors[0]
tensors[0] = aux_tensor
# Right node
aux_tensor = torch.zeros(*self._mats_env[-1].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0] = tensors[-1]
tensors[-1] = aux_tensor
@@ -1080,16 +1091,20 @@ Source code for tensorkrowch.models.mps
for i, node in enumerate(self._mats_env):
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if add_eye:
aux_tensor = node.tensor.detach()
aux_tensor[:, 0, :] += torch.eye(node.shape[0],
node.shape[2],
- device=device)
+ device=device,
+ dtype=dtype)
node.tensor = aux_tensor
if self._boundary == 'obc':
- aux_tensor = torch.zeros(*node.shape, device=device)
+ aux_tensor = torch.zeros(*node.shape,
+ device=device,
+ dtype=dtype)
if i == 0:
# Left node
aux_tensor[0] = node.tensor[0]
@@ -1100,8 +1115,12 @@ Source code for tensorkrowch.models.mps
node.tensor = aux_tensor
if self._boundary == 'obc':
- self._left_node.set_tensor(init_method='copy', device=device)
- self._right_node.set_tensor(init_method='copy', device=device)
+ self._left_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
+ self._right_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
[docs] def set_data_nodes(self) -> None:
"""
@@ -1139,7 +1158,8 @@ Source code for tensorkrowch.models.mps
out_features=self._out_features,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
for new_node, node in zip(new_mps._mats_env, self._mats_env):
@@ -1552,10 +1572,10 @@ Source code for tensorkrowch.models.mps
copied_nodes = []
for node in nodes_out_env:
copied_node = node.__class__(shape=node._shape,
- axes_names=node.axes_names,
- name='virtual_result_copy',
- network=self,
- virtual=True)
+ axes_names=node.axes_names,
+ name='virtual_result_copy',
+ network=self,
+ virtual=True)
copied_node.set_tensor_from(node)
copied_nodes.append(copied_node)
@@ -1643,6 +1663,12 @@ Source code for tensorkrowch.models.mps
# Connect copies directly to output nodes
copied_node['input'] ^ node['input']
+ # If MPS nodes are complex, copied nodes are their conjugates
+ is_complex = copied_nodes[0].is_complex()
+ if is_complex:
+ for i, node in enumerate(copied_nodes):
+ copied_nodes[i] = node.conj()
+
# Contract output nodes with copies
mats_out_env = self._input_contraction(
nodes_env=nodes_out_env,
@@ -1764,6 +1790,12 @@ Source code for tensorkrowch.models.mps
copied_nodes = []
for node in all_nodes:
copied_nodes.append(node.neighbours('input'))
+
+ # If MPS nodes are complex, copied nodes are their conjugates
+ is_complex = copied_nodes[0].is_complex()
+ if is_complex:
+ for i, node in enumerate(copied_nodes):
+ copied_nodes[i] = node.conj()
# Contract output nodes with copies
mats_out_env = self._input_contraction(
@@ -1872,10 +1904,14 @@ Source code for tensorkrowch.models.mps
if n_dims >= 1:
if n_dims == 1:
data = torch.cat(data, dim=-1)
- data = basis(data, dim=dims[0]).float().to(self.in_env[0].device)
+ data = basis(data, dim=dims[0])\
+ .to(self.in_env[0].dtype)\
+ .to(self.in_env[0].device)
elif n_dims > 1:
data = [
- basis(dat, dim=dim).squeeze(-2).float().to(self.in_env[0].device)
+ basis(dat, dim=dim).squeeze(-2)\
+ .to(self.in_env[0].dtype)\
+ .to(self.in_env[0].device)
for dat, dim in zip(data, dims)
]
@@ -2002,7 +2038,7 @@ Source code for tensorkrowch.models.mps
middle_tensor.shape[-1]), # right
full_matrices=False)
- s = s[s > 0]
+ s = s[s.pow(2) > 0]
entropy = -(s.pow(2) * s.pow(2).log()).sum()
# Rescale
@@ -2195,6 +2231,7 @@ Source code for tensorkrowch.models.mps
side: Text = 'right'):
"""Projects all nodes into a space of dimension ``bond_dim``."""
device = nodes[0].tensor.device
+ dtype = nodes[0].tensor.dtype
if side == 'left':
nodes.reverse()
@@ -2219,7 +2256,7 @@ Source code for tensorkrowch.models.mps
proj_mat_node.tensor = torch.eye(
torch.tensor(phys_dim_lst).prod().int().item(),
- bond_dim).view(*phys_dim_lst, -1).to(device)
+ bond_dim).view(*phys_dim_lst, -1).to(dtype).to(device)
for k in range(j + 1):
nodes[k]['input'] ^ proj_mat_node[k]
@@ -2239,7 +2276,7 @@ Source code for tensorkrowch.models.mps
proj_mat_node.tensor = torch.eye(
torch.tensor(phys_dim_lst).prod().int().item(),
- bond_dim).view(*phys_dim_lst, -1).to(device)
+ bond_dim).view(*phys_dim_lst, -1).to(dtype).to(device)
for k in range(j + 1):
nodes[k]['input'] ^ proj_mat_node[k]
@@ -2256,7 +2293,8 @@ Source code for tensorkrowch.models.mps
name=f'proj_vec_node_{side}_({k})',
network=self)
- proj_vec_node.tensor = torch.eye(phys_dim, 1).squeeze().to(device)
+ proj_vec_node.tensor = torch.eye(phys_dim, 1).squeeze()\
+ .to(dtype).to(device)
nodes[k]['input'] ^ proj_vec_node['input']
line_mat_nodes.append(proj_vec_node @ nodes[k])
@@ -2424,6 +2462,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -2452,6 +2492,7 @@ Source code for tensorkrowch.models.mps
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
tensors = None
@@ -2493,6 +2534,7 @@ Source code for tensorkrowch.models.mps
n_batches=n_batches,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.name = 'umps'
@@ -2513,7 +2555,9 @@ Source code for tensorkrowch.models.mps
for node in self._mats_env:
node.set_tensor_from(uniform_memory)
- def _make_canonical(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_canonical(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS in canonical form with
orthogonality center at the rightmost node. Unitaries in nodes are
@@ -2527,13 +2571,15 @@ Source code for tensorkrowch.models.mps
size = max(aux_shape[0], aux_shape[1])
phys_dim = node_shape[1]
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:min(aux_shape[0], size), :min(aux_shape[1], size)]
tensor = tensor.reshape(*node_shape)
tensor = tensor * sqrt(phys_dim)
return tensor
- def _make_unitaries(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_unitaries(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS nodes as stacks of
unitaries.
@@ -2543,7 +2589,7 @@ Source code for tensorkrowch.models.mps
units = []
for _ in range(node_shape[1]):
- tensor = random_unitary(node_shape[0], device=device)
+ tensor = random_unitary(node_shape[0], device=device, dtype=dtype)
units.append(tensor)
tensor = torch.stack(units, dim=1)
return tensor
@@ -2552,6 +2598,7 @@ Source code for tensorkrowch.models.mps
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes the common tensor of the :class:`UMPS`. It can be called
@@ -2561,7 +2608,7 @@ Source code for tensorkrowch.models.mps
* ``{"zeros", "ones", "copy", "rand", "randn"}``: The tensor is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
* ``"randn_eye"``: Tensor is initialized as in this
`paper <https://arxiv.org/abs/1605.03795>`_, adding identities at the
@@ -2588,6 +2635,8 @@ Source code for tensorkrowch.models.mps
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -2595,9 +2644,9 @@ Source code for tensorkrowch.models.mps
node = self.uniform_memory
if init_method == 'unit':
- tensors = [self._make_unitaries(device=device)]
+ tensors = [self._make_unitaries(device=device, dtype=dtype)]
elif init_method == 'canonical':
- tensors = [self._make_canonical(device=device)]
+ tensors = [self._make_canonical(device=device, dtype=dtype)]
if tensors is not None:
node.tensor = tensors[0]
@@ -2610,12 +2659,14 @@ Source code for tensorkrowch.models.mps
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if add_eye:
aux_tensor = node.tensor.detach()
aux_tensor[:, 0, :] += torch.eye(node.shape[0],
node.shape[2],
- device=device)
+ device=device,
+ dtype=dtype)
node.tensor = aux_tensor
[docs] def copy(self, share_tensors: bool = False) -> 'UMPS':
@@ -2644,7 +2695,8 @@ Source code for tensorkrowch.models.mps
out_features=self._out_features,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
new_mps.uniform_memory.tensor = self.uniform_memory.tensor
@@ -2788,6 +2840,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -2829,6 +2883,7 @@ Source code for tensorkrowch.models.mps
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
phys_dim = None
@@ -2890,6 +2945,7 @@ Source code for tensorkrowch.models.mps
n_batches=n_batches,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.name = 'mpslayer'
self._in_dim = self._phys_dim[:out_position] + \
@@ -2919,7 +2975,9 @@ Source code for tensorkrowch.models.mps
"""Returns the output node."""
return self._mats_env[self._out_position]
- def _make_canonical(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_canonical(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS in canonical form with
orthogonality center at the rightmost node. Unitaries in nodes are
@@ -2944,14 +3002,16 @@ Source code for tensorkrowch.models.mps
phys_dim = node_shape[1]
size = max(aux_shape[0], aux_shape[1])
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:min(aux_shape[0], size), :min(aux_shape[1], size)]
tensor = tensor.reshape(*node_shape)
left_tensors.append(tensor * sqrt(phys_dim))
# Output node
- out_tensor = torch.randn(self.out_node.shape, device=device)
+ out_tensor = torch.randn(self.out_node.shape,
+ device=device,
+ dtype=dtype)
phys_dim = out_tensor.shape[1]
if self._boundary == 'obc':
if self._out_position == 0:
@@ -2978,7 +3038,7 @@ Source code for tensorkrowch.models.mps
phys_dim = node_shape[1]
size = max(aux_shape[0], aux_shape[1])
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:min(aux_shape[0], size), :min(aux_shape[1], size)]
tensor = tensor.reshape(*node_shape)
@@ -2989,7 +3049,9 @@ Source code for tensorkrowch.models.mps
tensors = left_tensors + [out_tensor] + right_tensors
return tensors
- def _make_unitaries(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_unitaries(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS nodes as stacks of
unitaries.
@@ -3011,7 +3073,7 @@ Source code for tensorkrowch.models.mps
size_2 = min(node.shape[2], size)
for _ in range(node.shape[1]):
- tensor = random_unitary(size, device=device)
+ tensor = random_unitary(size, device=device, dtype=dtype)
tensor = tensor[:size_1, :size_2]
units.append(tensor)
@@ -3026,7 +3088,9 @@ Source code for tensorkrowch.models.mps
left_tensors.append(units)
# Output node
- out_tensor = torch.randn(self.out_node.shape, device=device)
+ out_tensor = torch.randn(self.out_node.shape,
+ device=device,
+ dtype=dtype)
if self._boundary == 'obc':
if self._out_position == 0:
out_tensor = out_tensor[0]
@@ -3050,7 +3114,7 @@ Source code for tensorkrowch.models.mps
size_2 = min(node.shape[2], size)
for _ in range(node.shape[1]):
- tensor = random_unitary(size, device=device).t()
+ tensor = random_unitary(size, device=device, dtype=dtype).H
tensor = tensor[:size_1, :size_2]
units.append(tensor)
@@ -3068,63 +3132,12 @@ Source code for tensorkrowch.models.mps
# All tensors
tensors = left_tensors + [out_tensor] + right_tensors
return tensors
-
- def initialize(self,
- tensors: Optional[Sequence[torch.Tensor]] = None,
- init_method: Optional[Text] = 'randn',
- device: Optional[torch.device] = None,
- **kwargs: float) -> None:
- """
- Initializes all the nodes of the :class:`MPS`. It can be called when
- instantiating the model, or to override the existing nodes' tensors.
-
- There are different methods to initialize the nodes:
-
- * ``{"zeros", "ones", "copy", "rand", "randn"}``: Each node is
- initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
-
- * ``"randn_eye"``: Nodes are initialized as in this
- `paper <https://arxiv.org/abs/1605.03795>`_, adding identities at the
- top of random gaussian tensors. In this case, ``std`` should be
- specified with a low value, e.g., ``std = 1e-9``.
-
- * ``"unit"``: Nodes are initialized as stacks of random unitaries. This,
- combined (at least) with an embedding of the inputs as elements of
- the computational basis (:func:`~tensorkrowch.embeddings.discretize`
- combined with :func:`~tensorkrowch.embeddings.basis`)
-
- * ``"canonical"```: MPS is initialized in canonical form with a squared
- norm `close` to the product of all the physical dimensions (if bond
- dimensions are bigger than the powers of the physical dimensions,
- the norm could vary). Th orthogonality center is at the rightmost
- node.
-
- Parameters
- ----------
- tensors : list[torch.Tensor] or tuple[torch.Tensor], optional
- Sequence of tensors to set in each of the MPS nodes. If ``boundary``
- is ``"obc"``, all tensors should be rank-3, except the first and
- last ones, which can be rank-2, or rank-1 (if the first and last are
- the same). If ``boundary`` is ``"pbc"``, all tensors should be
- rank-3.
- init_method : {"zeros", "ones", "copy", "rand", "randn", "randn_eye", "unit", "canonical"}, optional
- Initialization method.
- device : torch.device, optional
- Device where to initialize the tensors if ``init_method`` is provided.
- kwargs : float
- Keyword arguments for the different initialization methods. See
- :meth:`~tensorkrowch.AbstractNode.make_tensor`.
- """
- if init_method == 'unit':
- tensors = self._make_unitaries(device=device)
- elif init_method == 'canonical':
- tensors = self._make_canonical(device=device)
[docs] def initialize(self,
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes all the nodes of the :class:`MPSLayer`. It can be called when
@@ -3134,7 +3147,7 @@ Source code for tensorkrowch.models.mps
* ``{"zeros", "ones", "copy", "rand", "randn"}``: Each node is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
* ``"randn_eye"``: Nodes are initialized as in this
`paper <https://arxiv.org/abs/1605.03795>`_, adding identities at the
@@ -3163,14 +3176,16 @@ Source code for tensorkrowch.models.mps
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
"""
if init_method == 'unit':
- tensors = self._make_unitaries(device=device)
+ tensors = self._make_unitaries(device=device, dtype=dtype)
elif init_method == 'canonical':
- tensors = self._make_canonical(device=device)
+ tensors = self._make_canonical(device=device, dtype=dtype)
if tensors is not None:
if len(tensors) != self._n_features:
@@ -3182,19 +3197,23 @@ Source code for tensorkrowch.models.mps
if device is None:
device = tensors[0].device
+ if dtype is None:
+ dtype = tensors[0].dtype
if len(tensors) == 1:
tensors[0] = tensors[0].reshape(1, -1, 1)
else:
# Left node
aux_tensor = torch.zeros(*self._mats_env[0].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[0] = tensors[0]
tensors[0] = aux_tensor
# Right node
aux_tensor = torch.zeros(*self._mats_env[-1].shape,
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0] = tensors[-1]
tensors[-1] = aux_tensor
@@ -3210,12 +3229,14 @@ Source code for tensorkrowch.models.mps
for i, node in enumerate(self._mats_env):
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if add_eye:
aux_tensor = node.tensor.detach()
eye_tensor = torch.eye(node.shape[0],
node.shape[2],
- device=device)
+ device=device,
+ dtype=dtype)
if i == self._out_position:
eye_tensor = eye_tensor.unsqueeze(1)
eye_tensor = eye_tensor.expand(node.shape)
@@ -3225,7 +3246,9 @@ Source code for tensorkrowch.models.mps
node.tensor = aux_tensor
if self._boundary == 'obc':
- aux_tensor = torch.zeros(*node.shape, device=device)
+ aux_tensor = torch.zeros(*node.shape,
+ device=device,
+ dtype=dtype)
if i == 0:
# Left node
aux_tensor[0] = node.tensor[0]
@@ -3236,8 +3259,12 @@ Source code for tensorkrowch.models.mps
node.tensor = aux_tensor
if self._boundary == 'obc':
- self._left_node.set_tensor(init_method='copy', device=device)
- self._right_node.set_tensor(init_method='copy', device=device)
+ self._left_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
+ self._right_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
[docs] def copy(self, share_tensors: bool = False) -> 'MPSLayer':
"""
@@ -3266,7 +3293,8 @@ Source code for tensorkrowch.models.mps
tensors=None,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
for new_node, node in zip(new_mps._mats_env, self._mats_env):
@@ -3328,6 +3356,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -3358,6 +3388,7 @@ Source code for tensorkrowch.models.mps
n_batches: int = 1,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
phys_dim = None
@@ -3433,6 +3464,7 @@ Source code for tensorkrowch.models.mps
n_batches=n_batches,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.name = 'umpslayer'
self._in_dim = self._phys_dim[:out_position] + \
@@ -3481,7 +3513,9 @@ Source code for tensorkrowch.models.mps
for node in in_nodes:
node.set_tensor_from(uniform_memory)
- def _make_canonical(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_canonical(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS in canonical form with
orthogonality center at the rightmost node. Unitaries in nodes are
@@ -3496,18 +3530,22 @@ Source code for tensorkrowch.models.mps
size = max(aux_shape[0], aux_shape[1])
phys_dim = node_shape[1]
- uni_tensor = random_unitary(size, device=device)
+ uni_tensor = random_unitary(size, device=device, dtype=dtype)
uni_tensor = uni_tensor[:min(aux_shape[0], size), :min(aux_shape[1], size)]
uni_tensor = uni_tensor.reshape(*node_shape)
uni_tensor = uni_tensor * sqrt(phys_dim)
# Output node
- out_tensor = torch.randn(self.out_node.shape, device=device)
+ out_tensor = torch.randn(self.out_node.shape,
+ device=device,
+ dtype=dtype)
out_tensor = out_tensor / out_tensor.norm() * sqrt(out_tensor.shape[1])
return [uni_tensor, out_tensor]
- def _make_unitaries(self, device: Optional[torch.device] = None) -> List[torch.Tensor]:
+ def _make_unitaries(self,
+ device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None) -> List[torch.Tensor]:
"""
Creates random unitaries to initialize the MPS nodes as stacks of
unitaries.
@@ -3518,7 +3556,9 @@ Source code for tensorkrowch.models.mps
units = []
for _ in range(node_shape[1]):
- tensor = random_unitary(node_shape[0], device=device)
+ tensor = random_unitary(node_shape[0],
+ device=device,
+ dtype=dtype)
units.append(tensor)
tensors.append(torch.stack(units, dim=1))
@@ -3529,6 +3569,7 @@ Source code for tensorkrowch.models.mps
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes the common tensor of the :class:`UMPSLayer`. It can be called
@@ -3538,7 +3579,7 @@ Source code for tensorkrowch.models.mps
* ``{"zeros", "ones", "copy", "rand", "randn"}``: The tensor is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
* ``"randn_eye"``: Tensor is initialized as in this
`paper <https://arxiv.org/abs/1605.03795>`_, adding identities at the
@@ -3566,14 +3607,16 @@ Source code for tensorkrowch.models.mps
Initialization method.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
"""
if init_method == 'unit':
- tensors = self._make_unitaries(device=device)
+ tensors = self._make_unitaries(device=device, dtype=dtype)
elif init_method == 'canonical':
- tensors = self._make_canonical(device=device)
+ tensors = self._make_canonical(device=device, dtype=dtype)
if tensors is not None:
self.uniform_memory.tensor = tensors[0]
@@ -3588,12 +3631,14 @@ Source code for tensorkrowch.models.mps
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if add_eye:
aux_tensor = node.tensor.detach()
eye_tensor = torch.eye(node.shape[0],
node.shape[2],
- device=device)
+ device=device,
+ dtype=dtype)
if i == 0:
aux_tensor[:, 0, :] += eye_tensor
else:
@@ -3628,7 +3673,8 @@ Source code for tensorkrowch.models.mps
tensor=None,
n_batches=self._n_batches,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
new_mps.uniform_memory.tensor = self.uniform_memory.tensor
@@ -3869,6 +3915,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -3895,6 +3943,7 @@ Source code for tensorkrowch.models.mps
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs):
unfold = self._set_attributes(in_channels=in_channels,
@@ -3912,6 +3961,7 @@ Source code for tensorkrowch.models.mps
n_batches=2,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.unfold = unfold
@@ -3980,7 +4030,8 @@ Source code for tensorkrowch.models.mps
boundary=self._boundary,
tensors=None,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
for new_node, node in zip(new_mps._mats_env, self._mats_env):
@@ -4032,6 +4083,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -4061,6 +4114,7 @@ Source code for tensorkrowch.models.mps
tensor: Optional[torch.Tensor] = None,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs):
unfold = self._set_attributes(in_channels=in_channels,
@@ -4077,6 +4131,7 @@ Source code for tensorkrowch.models.mps
n_batches=2,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self.unfold = unfold
@@ -4144,7 +4199,8 @@ Source code for tensorkrowch.models.mps
dilation=self.dilation,
tensor=None,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
new_mps.uniform_memory.tensor = self.uniform_memory.tensor
@@ -4212,6 +4268,8 @@ Source code for tensorkrowch.models.mps
explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -4241,6 +4299,7 @@ Source code for tensorkrowch.models.mps
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs):
unfold = self._set_attributes(in_channels=in_channels,
@@ -4261,6 +4320,7 @@ Source code for tensorkrowch.models.mps
n_batches=2,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self._out_channels = out_channels
@@ -4336,7 +4396,8 @@ Source code for tensorkrowch.models.mps
boundary=self._boundary,
tensors=None,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
for new_node, node in zip(new_mps._mats_env, self._mats_env):
@@ -4397,6 +4458,8 @@ Source code for tensorkrowch.models.mps
detailed explanation of the different initialization methods.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -4429,6 +4492,7 @@ Source code for tensorkrowch.models.mps
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Text = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs):
unfold = self._set_attributes(in_channels=in_channels,
@@ -4448,6 +4512,7 @@ Source code for tensorkrowch.models.mps
n_batches=2,
init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
self._out_channels = out_channels
@@ -4527,7 +4592,8 @@ Source code for tensorkrowch.models.mps
dilation=self.dilation,
tensor=None,
init_method=None,
- device=None)
+ device=None,
+ dtype=None)
new_mps.name = self.name + '_copy'
if share_tensors:
new_mps.uniform_memory.tensor = self.uniform_memory.tensor
diff --git a/docs/_build/html/_modules/tensorkrowch/models/mps_data.html b/docs/_build/html/_modules/tensorkrowch/models/mps_data.html
index 07bb2a2..424d1f6 100644
--- a/docs/_build/html/_modules/tensorkrowch/models/mps_data.html
+++ b/docs/_build/html/_modules/tensorkrowch/models/mps_data.html
@@ -5,7 +5,7 @@
- tensorkrowch.models.mps_data — TensorKrowch 1.1.2 documentation
+ tensorkrowch.models.mps_data — TensorKrowch 1.1.3 documentation
@@ -413,6 +413,8 @@ Source code for tensorkrowch.models.mps_data
:meth:`add_data` to see how to initialize MPS nodes with data tensors.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
@@ -439,6 +441,7 @@ Source code for tensorkrowch.models.mps_data
tensors: Optional[Sequence[torch.Tensor]] = None,
init_method: Optional[Text] = None,
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs) -> None:
super().__init__(name='mps_data')
@@ -568,6 +571,7 @@ Source code for tensorkrowch.models.mps_data
self._make_nodes()
self.initialize(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if tensors is not None:
@@ -616,6 +620,15 @@ Source code for tensorkrowch.models.mps_data
"""Returns the list of nodes in ``mats_env``."""
return self._mats_env
+ @property
+ def tensors(self) -> List[torch.Tensor]:
+ """Returns the list of MPS tensors."""
+ mps_tensors = [node.tensor for node in self._mats_env]
+ if self._boundary == 'obc':
+ mps_tensors[0] = mps_tensors[0][0, :, :]
+ mps_tensors[-1] = mps_tensors[-1][:, :, 0]
+ return mps_tensors
+
# -------
# Methods
# -------
@@ -673,6 +686,7 @@ Source code for tensorkrowch.models.mps_data
[docs] def initialize(self,
init_method: Optional[Text] = 'randn',
device: Optional[torch.device] = None,
+ dtype: Optional[torch.dtype] = None,
**kwargs: float) -> None:
"""
Initializes all the nodes of the :class:`MPSData`. It can be called when
@@ -682,7 +696,7 @@ Source code for tensorkrowch.models.mps_data
* ``{"zeros", "ones", "copy", "rand", "randn"}``: Each node is
initialized calling :meth:`~tensorkrowch.AbstractNode.set_tensor` with
- the given method, ``device`` and ``kwargs``.
+ the given method, ``device``, ``dtype`` and ``kwargs``.
Parameters
----------
@@ -691,22 +705,31 @@ Source code for tensorkrowch.models.mps_data
initialize MPS nodes with data tensors.
device : torch.device, optional
Device where to initialize the tensors if ``init_method`` is provided.
+ dtype : torch.dtype, optional
+ Dtype of the tensor if ``init_method`` is provided.
kwargs : float
Keyword arguments for the different initialization methods. See
:meth:`~tensorkrowch.AbstractNode.make_tensor`.
"""
if self._boundary == 'obc':
- self._left_node.set_tensor(init_method='copy', device=device)
- self._right_node.set_tensor(init_method='copy', device=device)
+ self._left_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
+ self._right_node.set_tensor(init_method='copy',
+ device=device,
+ dtype=dtype)
if init_method is not None:
for i, node in enumerate(self._mats_env):
node.set_tensor(init_method=init_method,
device=device,
+ dtype=dtype,
**kwargs)
if self._boundary == 'obc':
- aux_tensor = torch.zeros(*node.shape, device=device)
+ aux_tensor = torch.zeros(*node.shape,
+ device=device,
+ dtype=dtype)
if i == 0:
# Left node
aux_tensor[..., 0, :, :] = node.tensor[..., 0, :, :]
@@ -762,37 +785,45 @@ Source code for tensorkrowch.models.mps_data
data = data[:]
device = data[0].device
+ dtype = data[0].dtype
for i, node in enumerate(self._mats_env):
if self._boundary == 'obc':
- aux_tensor = torch.zeros(*node.shape, device=device)
if (i == 0) and (i == (self._n_features - 1)):
aux_tensor = torch.zeros(*data[i].shape[:-1],
*node.shape[-3:],
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0, :, 0] = data[i]
data[i] = aux_tensor
elif i == 0:
aux_tensor = torch.zeros(*data[i].shape[:-2],
*node.shape[-3:-1],
data[i].shape[-1],
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0, :, :] = data[i]
data[i] = aux_tensor
elif i == (self._n_features - 1):
aux_tensor = torch.zeros(*data[i].shape[:-1],
*node.shape[-2:],
- device=device)
+ device=device,
+ dtype=dtype)
aux_tensor[..., 0] = data[i]
data[i] = aux_tensor
node._direct_set_tensor(data[i])
- # Send left and right nodes to correct device
+ # Send left and right nodes to correct device and dtype
if self._boundary == 'obc':
if self._left_node.device != device:
self._left_node.tensor = self._left_node.tensor.to(device)
+ if self._left_node.dtype != dtype:
+ self._left_node.tensor = self._left_node.tensor.to(dtype)
+
if self._right_node.device != device:
self._right_node.tensor = self._right_node.tensor.to(device)
+ if self._right_node.dtype != dtype:
+ self._right_node.tensor = self._right_node.tensor.to(dtype)
# Update bond dim
if self._boundary == 'obc':
diff --git a/docs/_build/html/_modules/tensorkrowch/models/peps.html b/docs/_build/html/_modules/tensorkrowch/models/peps.html
index 3c67433..1d26549 100644
--- a/docs/_build/html/_modules/tensorkrowch/models/peps.html
+++ b/docs/_build/html/_modules/tensorkrowch/models/peps.html
@@ -5,7 +5,7 @@
- tensorkrowch.models.peps — TensorKrowch 1.1.2 documentation
+ tensorkrowch.models.peps — TensorKrowch 1.1.3 documentation
diff --git a/docs/_build/html/_modules/tensorkrowch/models/tree.html b/docs/_build/html/_modules/tensorkrowch/models/tree.html
index ec2b696..c57a6ce 100644
--- a/docs/_build/html/_modules/tensorkrowch/models/tree.html
+++ b/docs/_build/html/_modules/tensorkrowch/models/tree.html
@@ -5,7 +5,7 @@
- tensorkrowch.models.tree — TensorKrowch 1.1.2 documentation
+ tensorkrowch.models.tree — TensorKrowch 1.1.3 documentation
diff --git a/docs/_build/html/_modules/tensorkrowch/operations.html b/docs/_build/html/_modules/tensorkrowch/operations.html
index 82dbc4b..ddf3449 100644
--- a/docs/_build/html/_modules/tensorkrowch/operations.html
+++ b/docs/_build/html/_modules/tensorkrowch/operations.html
@@ -5,7 +5,7 @@
- tensorkrowch.operations — TensorKrowch 1.1.2 documentation
+ tensorkrowch.operations — TensorKrowch 1.1.3 documentation
@@ -336,8 +336,11 @@ Source code for tensorkrowch.operations
* permute_ (in-place)
* tprod
* mul
+ * div
* add
* sub
+ * renormalize
+ * conj
Node-like operations:
* split
@@ -1793,6 +1796,120 @@ Source code for tensorkrowch.operations
AbstractNode.renormalize = renormalize_node
+################################## conj ##################################
+# MARK: conj
+def _check_first_conj(node: AbstractNode) -> Optional[Successor]:
+ args = (node,)
+ successors = node._successors.get('conj')
+ if not successors:
+ return None
+ return successors.get(args)
+
+
+def _conj_first(node: AbstractNode) -> Node:
+ new_node = Node._create_resultant(axes_names=node.axes_names,
+ name='conj',
+ network=node._network,
+ tensor=node.tensor.conj(),
+ edges=node._edges,
+ node1_list=node.is_node1())
+
+ # Create successor
+ net = node._network
+ args = (node,)
+ successor = Successor(node_ref=node.node_ref(),
+ index=node._tensor_info['index'],
+ child=new_node)
+
+ # Add successor to parent
+ if 'conj' in node._successors:
+ node._successors['conj'].update({args: successor})
+ else:
+ node._successors['conj'] = {args: successor}
+
+ # Add operation to list of performed operations of TN
+ net._seq_ops.append(('conj', args))
+
+ # Record in inverse_memory while tracing
+ if net._tracing:
+ node._record_in_inverse_memory()
+
+ return new_node
+
+
+def _conj_next(successor: Successor, node: AbstractNode) -> Node:
+ tensor = node._direct_get_tensor(successor.node_ref,
+ successor.index)
+ child = successor.child
+ child._direct_set_tensor(tensor.conj())
+
+ # Record in inverse_memory while contracting, if network is traced
+ # (to delete memory if possible)
+ if node._network._traced:
+ node._check_inverse_memory(successor.node_ref)
+
+ return child
+
+
+conj_op = Operation('conj',
+ _check_first_conj,
+ _conj_first,
+ _conj_next)
+
+
+def conj(node: AbstractNode) -> Node:
+ """
+ Returns a view of the node's tensor with a flipped conjugate bit. If the
+ node has a non-complex dtype, this function returns a new node with the
+ same tensor.
+
+ See `conj <https://pytorch.org/docs/stable/generated/torch.conj.html>`_
+ in the **PyTorch** documentation.
+
+ Parameters
+ ----------
+ node : Node or ParamNode
+ Node that is to be conjugated.
+
+ Returns
+ -------
+ Node
+
+ Examples
+ --------
+ >>> nodeA = tk.randn((3, 3), dtype=torch.complex64)
+ >>> conjA = tk.conj(nodeA)
+ >>> conjA.is_conj()
+ True
+ """
+ return conj_op(node)
+
+
+conj_node = copy_func(conj)
+conj_node.__doc__ = \
+ """
+ Returns a view of the node's tensor with a flipped conjugate bit. If the
+ node has a non-complex dtype, this function returns a new node with the
+ same tensor.
+
+ See `conj <https://pytorch.org/docs/stable/generated/torch.conj.html>`_
+ in the **PyTorch** documentation.
+
+ Returns
+ -------
+ Node
+
+ Examples
+ --------
+ >>> nodeA = tk.randn((3, 3), dtype=torch.complex64)
+ >>> conjA = nodeA.conj()
+ >>> conjA.is_conj()
+ True
+ """
+
+AbstractNode.conj = conj_node
+
+
###############################################################################
# NODE-LIKE OPERATIONS #
###############################################################################
@@ -1926,9 +2043,12 @@ Source code for tensorkrowch.operations
u = u[..., :rank]
s = s[..., :rank]
vh = vh[..., :rank, :]
+
+ if u.is_complex():
+ s = s.to(u.dtype)
if mode == 'svdr':
- phase = torch.sign(torch.randn(s.shape))
+ phase = torch.sgn(torch.randn_like(s))
phase = torch.diag_embed(phase)
u = u @ phase
vh = phase @ vh
@@ -2125,9 +2245,12 @@ Source code for tensorkrowch.operations
u = u[..., :rank]
s = s[..., :rank]
vh = vh[..., :rank, :]
+
+ if u.is_complex():
+ s = s.to(u.dtype)
if mode == 'svdr':
- phase = torch.sign(torch.randn(s.shape))
+ phase = torch.sgn(torch.randn_like(s))
phase = torch.diag_embed(phase)
u = u @ phase
vh = phase @ vh
diff --git a/docs/_build/html/_sources/tutorials/0_first_steps.rst.txt b/docs/_build/html/_sources/tutorials/0_first_steps.rst.txt
index 05997e1..153719f 100644
--- a/docs/_build/html/_sources/tutorials/0_first_steps.rst.txt
+++ b/docs/_build/html/_sources/tutorials/0_first_steps.rst.txt
@@ -134,7 +134,7 @@ possible classes.
::
# Check if GPU is available
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
+ device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
# Instantiate model
mps = tk.models.MPSLayer(n_features=image_size[0] * image_size[1] + 1,
diff --git a/docs/_build/html/_static/documentation_options.js b/docs/_build/html/_static/documentation_options.js
index 5314893..3d088f5 100644
--- a/docs/_build/html/_static/documentation_options.js
+++ b/docs/_build/html/_static/documentation_options.js
@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
- VERSION: '1.1.2',
+ VERSION: '1.1.3',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
diff --git a/docs/_build/html/api.html b/docs/_build/html/api.html
index 04904b7..3001f29 100644
--- a/docs/_build/html/api.html
+++ b/docs/_build/html/api.html
@@ -6,7 +6,7 @@
- API Reference — TensorKrowch 1.1.2 documentation
+ API Reference — TensorKrowch 1.1.3 documentation
diff --git a/docs/_build/html/components.html b/docs/_build/html/components.html
index 79314d3..9888808 100644
--- a/docs/_build/html/components.html
+++ b/docs/_build/html/components.html
@@ -6,7 +6,7 @@
- Components — TensorKrowch 1.1.2 documentation
+ Components — TensorKrowch 1.1.3 documentation
@@ -705,7 +705,7 @@ Nodes
AbstractNode#
-
-