1
1
import math
2
2
import torch
3
- from torch import BoolTensor , LongTensor , Tensor
3
+ from torch import BoolTensor , LongTensor , FloatTensor , Tensor
4
4
import torch .nn .functional as F
5
5
from collections import deque
6
6
@@ -482,12 +482,13 @@ def bind(input: Tensor, other: Tensor) -> Tensor:
482
482
483
483
Examples::
484
484
485
- >>> x = functional.random_hv(2, 3)
486
- >>> x
487
- tensor([[ 1., -1., -1.],
488
- [ 1., 1., 1.]])
489
- >>> functional.bind(x[0], x[1])
490
- tensor([ 1., -1., -1.])
485
+ >>> a, b = functional.random_hv(2, 10)
486
+ >>> a
487
+ tensor([-1., 1., -1., -1., 1., 1., -1., 1., 1., -1.])
488
+ >>> b
489
+ tensor([-1., -1., 1., 1., -1., -1., 1., 1., 1., 1.])
490
+ >>> functional.bind(a, b)
491
+ tensor([ 1., -1., -1., -1., -1., -1., -1., 1., 1., -1.])
491
492
492
493
"""
493
494
dtype = input .dtype
@@ -571,12 +572,13 @@ def bundle(input: Tensor, other: Tensor, *, tie: BoolTensor = None) -> Tensor:
571
572
572
573
Examples::
573
574
574
- >>> x = functional.random_hv(2, 3)
575
- >>> x
576
- tensor([[ 1., 1., 1.],
577
- [-1., 1., -1.]])
578
- >>> functional.bundle(x[0], x[1])
579
- tensor([0., 2., 0.])
575
+ >>> a, b = functional.random_hv(2, 10)
576
+ >>> a
577
+ tensor([ 1., -1., 1., -1., -1., 1., -1., -1., 1., -1.])
578
+ >>> b
579
+ tensor([ 1., -1., -1., 1., 1., 1., -1., 1., -1., 1.])
580
+ >>> functional.bundle(a, b)
581
+ tensor([ 2., -2., 0., 0., 0., 2., -2., 0., 0., 0.])
580
582
581
583
"""
582
584
dtype = input .dtype
@@ -891,6 +893,91 @@ def multiset(input: Tensor) -> Tensor:
891
893
892
894
return torch .sum (input , dim = dim , dtype = dtype )
893
895
896
+ def randsel (
897
+ input : Tensor , other : Tensor , * , p : float = 0.5 , generator : torch .Generator = None
898
+ ) -> Tensor :
899
+ r"""Bundles two hypervectors by selecting random elements.
900
+
901
+ A bundling operation is used to aggregate information into a single hypervector.
902
+ The resulting hypervector has elements selected at random from input or other.
903
+
904
+ .. math::
905
+
906
+ \oplus: \mathcal{H} \times \mathcal{H} \to \mathcal{H}
907
+
908
+ Aliased as ``torchhd.randsel``.
909
+
910
+ Args:
911
+ input (Tensor): input hypervector
912
+ other (Tensor): other input hypervector
913
+ p (float, optional): probability of selecting elements from the input hypervector. Default: 0.5.
914
+ generator (``torch.Generator``, optional): a pseudorandom number generator for sampling.
915
+
916
+ Shapes:
917
+ - Input: :math:`(*)`
918
+ - Other: :math:`(*)`
919
+ - Output: :math:`(*)`
920
+
921
+ Examples::
922
+
923
+ >>> a, b = functional.random_hv(2, 10)
924
+ >>> a
925
+ tensor([ 1., -1., 1., -1., 1., -1., -1., -1., -1., 1.])
926
+ >>> b
927
+ tensor([ 1., -1., 1., -1., 1., 1., -1., 1., -1., 1.])
928
+ >>> functional.randsel(a, b)
929
+ tensor([ 1., -1., 1., -1., 1., 1., -1., 1., -1., 1.])
930
+
931
+ """
932
+ select = torch .empty_like (input , dtype = torch .bool )
933
+ select .bernoulli_ (1 - p , generator = generator )
934
+ return input .where (select , other )
935
+
936
+
937
+ def multirandsel (
938
+ input : Tensor , * , p : FloatTensor = None , generator : torch .Generator = None
939
+ ) -> Tensor :
940
+ r"""Bundling multiple hypervectors by sampling random elements.
941
+
942
+ Bundles all the input hypervectors together.
943
+ The resulting hypervector has elements selected at random from the input tensor of hypervectors.
944
+
945
+ .. math::
946
+
947
+ \bigoplus_{i=0}^{n-1} V_i
948
+
949
+ Args:
950
+ input (Tensor): input hypervector tensor
951
+ p (FloatTensor, optional): probability of selecting elements from the input hypervector. Default: uniform.
952
+ generator (``torch.Generator``, optional): a pseudorandom number generator for sampling.
953
+
954
+ Shapes:
955
+ - Input: :math:`(*, n, d)`
956
+ - Probability (p): :math:`(*, n)`
957
+ - Output: :math:`(*, d)`
958
+
959
+ Examples::
960
+
961
+ >>> x = functional.random_hv(5, 10)
962
+ >>> x
963
+ tensor([[-1., 1., 1., 1., -1., 1., 1., -1., 1., -1.],
964
+ [-1., 1., 1., 1., -1., 1., -1., -1., -1., -1.],
965
+ [-1., -1., 1., -1., -1., 1., -1., 1., 1., -1.],
966
+ [ 1., 1., -1., 1., -1., -1., 1., -1., 1., 1.],
967
+ [ 1., -1., -1., 1., 1., 1., 1., -1., -1., -1.]])
968
+ >>> functional.multirandsel(x)
969
+ tensor([ 1., -1., -1., 1., -1., 1., 1., 1., 1., -1.])
970
+
971
+ """
972
+ d = input .size (- 1 )
973
+ device = input .device
974
+
975
+ if p is None :
976
+ p = torch .ones (input .shape [:- 1 ], dtype = torch .float , device = device )
977
+
978
+ select = torch .multinomial (p , d , replacement = True , generator = generator )
979
+ select .unsqueeze_ (- 2 )
980
+ return input .gather (- 2 , select ).squeeze (- 2 )
894
981
895
982
multibundle = multiset
896
983
@@ -917,13 +1004,15 @@ def multibind(input: Tensor) -> Tensor:
917
1004
918
1005
Examples::
919
1006
920
- >>> x = functional.random_hv(3, 3 )
1007
+ >>> x = functional.random_hv(5, 10 )
921
1008
>>> x
922
- tensor([[ 1., 1., 1.],
923
- [-1., 1., 1.],
924
- [-1., 1., -1.]])
1009
+ tensor([[ 1., -1., -1., -1., -1., 1., 1., 1., -1., 1.],
1010
+ [ 1., 1., -1., -1., 1., 1., -1., -1., 1., -1.],
1011
+ [-1., -1., 1., -1., -1., -1., -1., 1., -1., -1.],
1012
+ [-1., 1., -1., 1., 1., -1., -1., -1., 1., 1.],
1013
+ [-1., -1., 1., -1., 1., -1., 1., 1., -1., 1.]])
925
1014
>>> functional.multibind(x)
926
- tensor([ 1., 1., - 1.])
1015
+ tensor([-1., - 1., -1., 1., 1., -1., -1., 1., -1., 1.])
927
1016
928
1017
"""
929
1018
dtype = input .dtype
0 commit comments