@@ -495,25 +495,27 @@ def from_vector(cls, data, shape, contains_weights):
495
495
496
496
def arrange (self , weight_factor = None , permutation = None ):
497
497
"""
498
- Arrange the rank-1 components of a :class:`pyttb.ktensor`. The
499
- columns are permuted in place, so you must make a copy before calling
500
- this method if you want to store the original :class:`pyttb.ktensor`.
501
- One of the parameters, either `weight_factor` or `permutation`
502
- must be passed, and passing both parameters leads to an error.
498
+ Arrange the rank-1 components of a :class:`pyttb.ktensor` in place.
499
+ If `permutation` is passed, the columns of `self.factor_matrices` are
500
+ arranged using the provided permutation, so you must make a copy
501
+ before calling this method if you want to store the original
502
+ :class:`pyttb.ktensor`. If `weight_factor` is passed, then the values
503
+ in `self.weights` are absorbed into
504
+ `self.factor_matrices[weight_factor]`. If no parameters are passed,
505
+ then the columns of `self.factor_matrices` are normalized and then
506
+ permuted such that the resulting `self.weights` are sorted by
507
+ magnitude, greatest to least. Passing both parameters leads to an
508
+ error.
503
509
504
510
Parameters
505
511
----------
506
512
weight_factor: int, optional
507
- The index of the factor that the weights will be absorbed into
508
- permutation: :class:`tuple`, :class:`list`, :class:`numpy.ndarray`, optional
513
+ The index of the factor matrix that the weights will be absorbed into.
514
+ permutation: :class:`tuple`, :class:`list`, or :class:`numpy.ndarray`, optional
509
515
The new order of the components of the :class:`pyttb.ktensor`
510
516
into which to permute. The permutation must be of length equal to
511
- the number of components of the :class:`pyttb.ktensor`, N, and
512
- must be a permutation of 1 to N.
513
-
514
- Returns
515
- -------
516
- :class:`pyttb.ktensor`
517
+ the number of components of the :class:`pyttb.ktensor`, `self.ncomponents`
518
+ and must be a permutation of [0,...,`self.ncomponents`-1].
517
519
518
520
Examples
519
521
--------
@@ -546,13 +548,40 @@ def arrange(self, weight_factor=None, permutation=None):
546
548
factor_matrices[1] =
547
549
[[6. 5.]
548
550
[8. 7.]]
549
- """
550
551
552
+ Normalize and permute columns such that `weights` are sorted in
553
+ decreasing order:
554
+
555
+ >>> K.arrange()
556
+ >>> print(K) # doctest: +ELLIPSIS
557
+ ktensor of shape 2 x 2
558
+ weights=[89.4427... 27.2029...]
559
+ factor_matrices[0] =
560
+ [[0.4472... 0.3162...]
561
+ [0.8944... 0.9486...]]
562
+ factor_matrices[1] =
563
+ [[0.6... 0.5812...]
564
+ [0.8... 0.8137...]]
565
+
566
+ Absorb the weights into the second factor:
567
+
568
+ >>> K.arrange(weight_factor=1)
569
+ >>> print(K) # doctest: +ELLIPSIS
570
+ ktensor of shape 2 x 2
571
+ weights=[1. 1.]
572
+ factor_matrices[0] =
573
+ [[0.4472... 0.3162...]
574
+ [0.8944... 0.9486...]]
575
+ factor_matrices[1] =
576
+ [[53.6656... 15.8113...]
577
+ [71.5541... 22.1359...]]
578
+ """
551
579
if permutation is not None and weight_factor is not None :
552
580
assert (
553
581
False
554
582
), "Weighting and permuting the ktensor at the same time is not allowed."
555
583
584
+ # arrange columns of factor matrices using the permutation provided
556
585
if permutation is not None and isinstance (
557
586
permutation , (tuple , list , np .ndarray )
558
587
):
@@ -566,8 +595,8 @@ def arrange(self, weight_factor=None, permutation=None):
566
595
False
567
596
), "Number of elements in permutation does not match number of components in ktensor."
568
597
569
- # TODO there is a relationship here between normalize and arrange that repeats tasks. Can this be made to be more efficient?
570
- # ensure that factor matrices are normalized
598
+ # TODO there is a relationship here between normalize and arrange that repeats tasks.
599
+ # Can this be made to be more efficient? ensure that factor matrices are normalized
571
600
self .normalize ()
572
601
573
602
# sort
@@ -576,16 +605,13 @@ def arrange(self, weight_factor=None, permutation=None):
576
605
for i in range (self .ndims ):
577
606
self .factor_matrices [i ] = self .factor_matrices [i ][:, p ]
578
607
579
- # TODO is this necessary? Matlab only absorbs into the last factor, not factor N as is documented
580
- # absorb weight into one factor if requested
608
+ # absorb the weights into one factor, optional
581
609
if weight_factor is not None :
582
- pass
583
- # if exist('foo','var')
584
- # r = length(X.lambda);
585
- # X.u{end} = full(X.u{end} * spdiags(X.lambda,0,r,r));
586
- # X.lambda = ones(size(X.lambda));
587
- # end
588
- return self
610
+ r = len (self .weights )
611
+ self .factor_matrices [weight_factor ] *= self .weights
612
+ self .weights = np .ones_like (self .weights )
613
+
614
+ return
589
615
590
616
def copy (self ):
591
617
"""
@@ -1260,7 +1286,7 @@ def norm(self):
1260
1286
def normalize (self , weight_factor = None , sort = False , normtype = 2 , mode = None ):
1261
1287
"""
1262
1288
Normalize the columns of the factor matrices of a
1263
- :class:`pyttb.ktensor`.
1289
+ :class:`pyttb.ktensor` in place .
1264
1290
1265
1291
Parameters
1266
1292
----------
@@ -1273,7 +1299,7 @@ def normalize(self, weight_factor=None, sort=False, normtype=2, mode=None):
1273
1299
normtype: {non-negative int, -1, -2, np.inf, -np.inf}, optional
1274
1300
Order of the norm (see :func:`numpy.linalg.norm` for possible
1275
1301
values).
1276
- mode: { int, None} , optional
1302
+ mode: int, optional
1277
1303
Index of factor matrix to normalize. A value of `None` means
1278
1304
normalize all factor matrices.
1279
1305
@@ -1284,7 +1310,7 @@ def normalize(self, weight_factor=None, sort=False, normtype=2, mode=None):
1284
1310
Examples
1285
1311
--------
1286
1312
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2)
1287
- >>> print(K.normalize()) # doctest: +ELLIPSIS
1313
+ >>> print(K.normalize()) # doctest: +ELLIPSIS
1288
1314
ktensor of shape 2 x 3 x 4
1289
1315
weights=[4.898... 4.898...]
1290
1316
factor_matrices[0] =
@@ -1310,7 +1336,7 @@ def normalize(self, weight_factor=None, sort=False, normtype=2, mode=None):
1310
1336
1.0 / tmp * self .factor_matrices [mode ][:, r ]
1311
1337
)
1312
1338
self .weights [r ] = self .weights [r ] * tmp
1313
- return
1339
+ return self
1314
1340
else :
1315
1341
assert (
1316
1342
False
@@ -1349,7 +1375,7 @@ def normalize(self, weight_factor=None, sort=False, normtype=2, mode=None):
1349
1375
if self .ncomponents > 1 :
1350
1376
# indices of srting in descending order
1351
1377
p = np .argsort (self .weights )[::- 1 ]
1352
- self = self .arrange (permutation = p )
1378
+ self .arrange (permutation = p )
1353
1379
1354
1380
return self
1355
1381
0 commit comments