# Sparse Tensors and Incomplete Tensors

>> Tensor Toolbox >> Tensor Types >> Sparse and Incomplete Tensors

MATLAB has no native ability to store sparse multidimensional arrays, only sparse matrices. Moreover, the compressed sparse column storage format for MATLAB sparse matrices is not readily adaptable to sparse tensors. Instead, the `sptensor` class stores the data in coordinate format. The `sptensor` class is best described in the following reference:

- B. W. Bader and T. G. Kolda. Efficient MATLAB Computations with Sparse and Factored Tensors, SIAM J. Scientific Computing, 30:205-231, 2007. http:dx.doi.org/10.1137/060676489.

As of Version 3.7, the `sptensor` class also supports incomplete tensors, meaning that it can store tensors where most values are missing (a scarce tensor). Only the known values and their subscripts are stored. The `type` flag of the `sptensor` is set to `'incomplete'` rather than `'sparse'`.

A sparse `sptensor` is such that only its nonzero entries are stored, and so every entry that is not explicitly stored is assumed to be zero. In contrast, an incomplete `sptensor` is such that every entry that is not explicitly stored is assumed to be missing, and so the value of those entries is unknown. An incomplete `sptensor` must store zeros explicitly; a sparse `sptensor` does not store zeros at all.

## Contents

- Creating a sptensor
- Specifying the accumulation method for the constructor
- Creating a one-dimensional sptensor.
- Creating an all-zero sptensor
- Constituent parts of a sptensor
- Creating a sparse tensor from its constituent parts
- Creating an empty sptensor
- Use function to create a random sptensor
- Use squeeze to remove singleton dimensions from a sptensor
- Use squash to remove empty slices from a sptensor
- Use full or tensor to convert a sptensor to a (dense) tensor
- Use sptensor to convert a (dense) tensor to a sptensor
- Use double to convert a sptensor to a (dense) multidimensional array
- Use find to extract nonzeros from a tensor and then create a sptensor
- Use ndims and size to get the size of a sptensor
- Use nnz to get the number of nonzeros of a sptensor
- Subscripted reference for a sptensor
- Subscripted assignment for a sptensor
- Use end as the last index.
- Use elemfun to manipulate the nonzeros of a sptensor
- Basic operations (plus, minus, times, etc.) on a sptensor
- Use permute to reorder the modes of a sptensor
- Displaying a tensor
- Creating an incomplete sptensor
- Functions that work differently for 'incomplete' sptensors
- Functions not defined for 'incomplete' sptensors

## Creating a sptensor

A sparse tensor can be created by passing in a list of subscripts and values. For example, here we pass in three subscripts and a scalar value. The resuling sparse tensor has three nonzero entries, and the size is the size of the largest subscript in each dimension.

    subs = [1,1,1;1,2,1;3,4,2]; %<-- Subscripts of the nonzeros
    vals = [1; 2; 3]; %<-- The values of the nonzeros
    X = sptensor(subs,vals) %<-- Create a sparse tensor with 3 nonzeros.

    X is a sparse tensor of size 3 x 4 x 2 with 3 values
    	(1,1,1)     1
    	(1,2,1)     2
    	(3,4,2)     3

    X = sptensor(subs,vals,[3 5 2]) %<-- Or, specify the size explicitly.

    X is a sparse tensor of size 3 x 5 x 2 with 3 values
    	(1,1,1)     1
    	(1,2,1)     2
    	(3,4,2)     3

Values corresponding to repeated subscripts are summed. Also note that we can use a scalar as the second argument.

    subs = [1 1 1; 1 1 3; 2 2 2; 4 4 4; 1 1 1; 1 1 1]; %<-- (1,1,1) is repeated.
    X = sptensor(subs,2) %<-- Equivalent to X = sptensor(subs,2*ones(6,1)).

    X is a sparse tensor of size 4 x 4 x 4 with 4 values
    	(1,1,1)     6
    	(1,1,3)     2
    	(2,2,2)     2
    	(4,4,4)     2

## Specifying the accumulation method for the constructor

By default, values corresponding to repeated elements are summed. However, it is possible to specify other actions to be taken.

    X = sptensor(subs,2*ones(6,1),[4 4 4],@max) %<-- Maximum element.

    X is a sparse tensor of size 4 x 4 x 4 with 4 values
    	(1,1,1)     2
    	(1,1,3)     2
    	(2,2,2)     2
    	(4,4,4)     2

    myfun = @(x) sum(x) / 3; %<-- Total sum divided by three.
    X = sptensor(subs,2*ones(6,1),[4 4 4],myfun) %<-- Custom accumulation function.

    X is a sparse tensor of size 4 x 4 x 4 with 4 values
    	(1,1,1)    2.0000
    	(1,1,3)    0.6667
    	(2,2,2)    0.6667
    	(4,4,4)    0.6667

## Creating a one-dimensional sptensor.

    X = sptensor([1;3;5],1,10) %<-- Same as X = sptensor([1;3;5],[1;1;1],1,10).

    X is a sparse tensor of size 10 with 3 values
    	(1)     1
    	(3)     1
    	(5)     1

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,50,5) %<-- A random, sparse, order-1 tensor with 5 nonzeros.

    X is a sparse tensor of size 50 with 5 values
    	(12)    0.7621
    	(25)    0.4565
    	(31)    0.0185
    	(45)    0.8214
    	(48)    0.4447

## Creating an all-zero sptensor

    X = sptensor([],[],[10 10 10]) %<-- Creates an all-zero tensor.

    X is an all-zero sparse tensor of size 10 x 10 x 10

    X = sptensor([10 10 10]) %<-- Same as above.

    X is an all-zero sparse tensor of size 10 x 10 x 10

## Constituent parts of a sptensor

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,[40 30 20],5); %<-- Create data.
    X.subs %<-- Subscripts of nonzeros.

    ans =

        10    14    16
        20    25    15
        25     1    19
        36    14     4
        39    23    13

    X.vals %<-- Corresponding nonzero values.

    ans =

        0.4057
        0.9355
        0.9169
        0.4103
        0.8936

    X.size %<-- The size.

    ans =

        40    30    20

    X.type %<-- The type, which is 'sparse' or 'incomplete'

    ans =

        'sparse'

## Creating a sparse tensor from its constituent parts

    Y = sptensor(X.subs,X.vals,X.size,[],X.type) %<-- Hard Way to Copy X

    Y is a sparse tensor of size 40 x 30 x 20 with 5 values
    	(10,14,16)    0.4057
    	(20,25,15)    0.9355
    	(25, 1,19)    0.9169
    	(36,14, 4)    0.4103
    	(39,23,13)    0.8936

    Y = X %<-- Easy way to copy X

    Y is a sparse tensor of size 40 x 30 x 20 with 5 values
    	(10,14,16)    0.4057
    	(20,25,15)    0.9355
    	(25, 1,19)    0.9169
    	(36,14, 4)    0.4103
    	(39,23,13)    0.8936

## Creating an empty sptensor

An empty constructor exists, primarily to support loads of previously saved data.

    Y = sptensor %<-- Create an empty sptensor.

    Y is an all-zero sparse tensor of size [empty tensor]

## Use function to create a random sptensor

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,[10 10 10],0.01) %<-- Create a tensor with 1% nonzeroes.

    X is a sparse tensor of size 10 x 10 x 10 with 10 values
    	( 1,10,7)    0.0153
    	( 3, 8,4)    0.7468
    	( 5, 8,1)    0.4451
    	( 5, 9,2)    0.9318
    	( 5,10,2)    0.4660
    	( 7,10,9)    0.4186
    	( 8, 5,3)    0.8462
    	( 9, 2,2)    0.5252
    	( 9, 5,3)    0.2026
    	(10, 7,1)    0.6721

It is also posible to specify the precise number of nonzeros rather than a percentage.

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,[10 10 10],10) %<-- Create a tensor with 10 nonzeros.

    X is a sparse tensor of size 10 x 10 x 10 with 10 values
    	( 1,10,7)    0.0153
    	( 3, 8,4)    0.7468
    	( 5, 8,1)    0.4451
    	( 5, 9,2)    0.9318
    	( 5,10,2)    0.4660
    	( 7,10,9)    0.4186
    	( 8, 5,3)    0.8462
    	( 9, 2,2)    0.5252
    	( 9, 5,3)    0.2026
    	(10, 7,1)    0.6721

## Use squeeze to remove singleton dimensions from a sptensor

    Y = sptensor([1 1 1; 2 1 1], 1, [2 1 1]) %<-- Create a sparse tensor.
    squeeze(Y) %<-- Remove singleton dimensions.

    Y is a sparse tensor of size 2 x 1 x 1 with 2 values
    	(1,1,1)     1
    	(2,1,1)     1
    ans is a sparse tensor of size 2 with 2 values
    	(1)     1
    	(2)     1

## Use squash to remove empty slices from a sptensor

    Y = sptensor([1 1 1; 3 3 3], [1; 3], [3 3 3]) %<-- Create a sparse tensor.
    squash(Y) %<-- Remove empty slices.

    Y is a sparse tensor of size 3 x 3 x 3 with 2 values
    	(1,1,1)     1
    	(3,3,3)     3
    ans is a sparse tensor of size 2 x 2 x 2 with 2 values
    	(1,1,1)     1
    	(2,2,2)     3

## Use full or tensor to convert a sptensor to a (dense) tensor

    X = sptensor([1 1 1; 2 2 2], [1; 1]); %<-- Create a sparse tensor.
    Y = full(X) %<-- Convert it to a (dense) tensor.

    Y is a tensor of size 2 x 2 x 2
    	Y(:,:,1) =
    	     1     0
    	     0     0
    	Y(:,:,2) =
    	     0     0
    	     0     1

    Y = tensor(X) %<-- Same as above.

    Y is a tensor of size 2 x 2 x 2
    	Y(:,:,1) =
    	     1     0
    	     0     0
    	Y(:,:,2) =
    	     0     0
    	     0     1

## Use sptensor to convert a (dense) tensor to a sptensor

    Z = sptensor(Y) %<-- Convert a tensor to a sptensor.

    Z is a sparse tensor of size 2 x 2 x 2 with 2 values
    	(1,1,1)     1
    	(2,2,2)     1

## Use double to convert a sptensor to a (dense) multidimensional array

    Y = double(X) %<-- Creates a MATLAB array.

    Y(:,:,1) =

         1     0
         0     0

    Y(:,:,2) =

         0     0
         0     1

## Use find to extract nonzeros from a tensor and then create a sptensor

The `find` command can be used to extract specific elements and then convert those into a sptensor.

    rand('state',0); %<-- Reproducible random numbers.
    X = tensor(rand(5,4,2),[5 4 2]) %<-- Create a tensor.
    S = find(X > 0.9) %<-- Extract subscipts of values greater than 0.9.
    V = X(S) %<-- Extract the corresponding values.
    Y = sptensor(S,V,[5 4 2]) %<-- Create a new tensor.

    X is a tensor of size 5 x 4 x 2
    	X(:,:,1) =
    	    0.9501    0.7621    0.6154    0.4057
    	    0.2311    0.4565    0.7919    0.9355
    	    0.6068    0.0185    0.9218    0.9169
    	    0.4860    0.8214    0.7382    0.4103
    	    0.8913    0.4447    0.1763    0.8936
    	X(:,:,2) =
    	    0.0579    0.2028    0.0153    0.4186
    	    0.3529    0.1987    0.7468    0.8462
    	    0.8132    0.6038    0.4451    0.5252
    	    0.0099    0.2722    0.9318    0.2026
    	    0.1389    0.1988    0.4660    0.6721

    S =

         1     1     1
         3     3     1
         2     4     1
         3     4     1
         4     3     2

    V =

        0.9501
        0.9218
        0.9355
        0.9169
        0.9318

    Y is a sparse tensor of size 5 x 4 x 2 with 5 values
    	(1,1,1)    0.9501
    	(2,4,1)    0.9355
    	(3,3,1)    0.9218
    	(3,4,1)    0.9169
    	(4,3,2)    0.9318

## Use ndims and size to get the size of a sptensor

    ndims(Y) %<-- Number of dimensions or modes.

    ans =

         3

    size(Y) %<-- Size of Y.

    ans =

         5     4     2

    size(Y,3) %<-- Size of mode 3 of Y.

    ans =

         2

## Use nnz to get the number of nonzeros of a sptensor

    nnz(Y) %<-- Number of nonzeros in Y.

    ans =

         5

## Subscripted reference for a sptensor

    X = sptensor([4,4,4;2,2,1;2,3,2],[3;5;1],[4 4 4]) %<-- Create a sptensor.

    X is a sparse tensor of size 4 x 4 x 4 with 3 values
    	(2,2,1)     5
    	(2,3,2)     1
    	(4,4,4)     3

    X(1,2,1) %<-- Extract the (1,2,1) element, which is zero.

    ans =

         0

    X(4,4,4) %<-- Extract the (4,4,4) element, which is nonzero.

    ans =

         3

    X(1:2,2:4,:) %<-- Extract a 2 x 3 x 4 subtensor.

    ans is a sparse tensor of size 2 x 3 x 4 with 2 values
    	(2,1,1)     5
    	(2,2,2)     1

    X([1 1 1; 2 2 1]) %<-- Extract elements by subscript.

    ans =

         0
         5

    X([1;6]) %<-- Same as above but with linear indices.

    ans =

         0
         5

As with a tensor, subscriped reference may be ambiguous for one-dimensional tensors.

    X = sptensor([1;3;5],1,7) %<-- Create a sparse tensor.

    X is a sparse tensor of size 7 with 3 values
    	(1)     1
    	(3)     1
    	(5)     1

    X(3) %<-- Fully specified, single elements are always returned as scalars.

    ans =

         1

    X([3;6]) %<-- Returns a subtensor.

    ans is a sparse tensor of size 2 with 1 values
    	(1)     1

    X([3;6],'extract') %<-- Same as above *but* returns an array.

    ans =

         1
         0

## Subscripted assignment for a sptensor

    X = sptensor([30 40 20]) %<-- Create an emtpy 30 x 40 x 20 sptensor.

    X is an all-zero sparse tensor of size 30 x 40 x 20

    X(30,40,20) = 7 %<-- Assign a single element.

    X is a sparse tensor of size 30 x 40 x 20 with 1 values
    	(30,40,20)     7

    X([1,1,1;2,2,2]) = [1;1] %<-- Assign a list of elements.

    X is a sparse tensor of size 30 x 40 x 20 with 3 values
    	(30,40,20)     7
    	( 1, 1, 1)     1
    	( 2, 2, 2)     1

    rand('state',0); %<-- Reproducible random numbers.
    X(11:20,11:20,11:20) = sptensor(@rand,[10,10,10],10) %<-- Assign a subtensor.

    X is a sparse tensor of size 30 x 40 x 20 with 13 values
    	(30,40,20)    7.0000
    	( 1, 1, 1)    1.0000
    	( 2, 2, 2)    1.0000
    	(11,20,17)    0.0153
    	(13,18,14)    0.7468
    	(15,18,11)    0.4451
    	(15,19,12)    0.9318
    	(15,20,12)    0.4660
    	(17,20,19)    0.4186
    	(18,15,13)    0.8462
    	(19,12,12)    0.5252
    	(19,15,13)    0.2026
    	(20,17,11)    0.6721

    X(31,41,21) = 4 %<-- Grows the size of the sptensor.

    X is a sparse tensor of size 31 x 41 x 21 with 14 values
    	(30,40,20)    7.0000
    	( 1, 1, 1)    1.0000
    	( 2, 2, 2)    1.0000
    	(11,20,17)    0.0153
    	(13,18,14)    0.7468
    	(15,18,11)    0.4451
    	(15,19,12)    0.9318
    	(15,20,12)    0.4660
    	(17,20,19)    0.4186
    	(18,15,13)    0.8462
    	(19,12,12)    0.5252
    	(19,15,13)    0.2026
    	(20,17,11)    0.6721
    	(31,41,21)    4.0000

    rand('state',1); %<-- Reproducible random numbers.
    X(111:120,111:120,111:120) = sptensor(@rand,[10,10,10],10) %<-- Grow more.

    X is a sparse tensor of size 120 x 120 x 120 with 24 values
    	( 30, 40, 20)    7.0000
    	(  1,  1,  1)    1.0000
    	(  2,  2,  2)    1.0000
    	( 11, 20, 17)    0.0153
    	( 13, 18, 14)    0.7468
    	( 15, 18, 11)    0.4451
    	( 15, 19, 12)    0.9318
    	( 15, 20, 12)    0.4660
    	( 17, 20, 19)    0.4186
    	( 18, 15, 13)    0.8462
    	( 19, 12, 12)    0.5252
    	( 19, 15, 13)    0.2026
    	( 20, 17, 11)    0.6721
    	( 31, 41, 21)    4.0000
    	(111,111,116)    0.3945
    	(114,118,116)    0.6916
    	(115,120,116)    0.5693
    	(116,114,113)    0.3432
    	(116,114,119)    0.5949
    	(118,115,111)    0.2739
    	(119,116,114)    0.0481
    	(119,116,115)    0.8381
    	(120,112,117)    0.1025
    	(120,119,118)    0.7283

## Use end as the last index.

    X(end-10:end,end-10:end,end-5:end)  %<-- Same as X(108:118,110:120,115:120)

    ans is a sparse tensor of size 11 x 11 x 6 with 7 values
    	( 2, 2,2)    0.3945
    	( 5, 9,2)    0.6916
    	( 6,11,2)    0.5693
    	( 7, 5,5)    0.5949
    	(10, 7,1)    0.8381
    	(11, 3,3)    0.1025
    	(11,10,4)    0.7283

## Use elemfun to manipulate the nonzeros of a sptensor

The function `elemfun` is similar to `spfun` for sparse matrices.

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,[10,10,10],3) %<-- Create some data.

    X is a sparse tensor of size 10 x 10 x 10 with 3 values
    	( 3,9,1)    0.4447
    	( 7,8,9)    0.6154
    	(10,5,5)    0.7919

    Z = elemfun(X, @sqrt) %<-- Square root of every nonzero.

    Z is a sparse tensor of size 10 x 10 x 10 with 3 values
    	( 3,9,1)    0.6669
    	( 7,8,9)    0.7845
    	(10,5,5)    0.8899

    Z = elemfun(X, @(x) x+1) %<-- Use a custom function.

    Z is a sparse tensor of size 10 x 10 x 10 with 3 values
    	( 3,9,1)    1.4447
    	( 7,8,9)    1.6154
    	(10,5,5)    1.7919

    Z = elemfun(X, @(x) x~=0) %<-- Set every nonzero to one.

    Z is a sparse tensor of size 10 x 10 x 10 with 3 values
    	( 3,9,1)   1
    	( 7,8,9)   1
    	(10,5,5)   1

    Z = ones(X) %<-- An easier way to change every nonzero to one.

    Z is a sparse tensor of size 10 x 10 x 10 with 3 values
    	( 3,9,1)     1
    	( 7,8,9)     1
    	(10,5,5)     1

## Basic operations (plus, minus, times, etc.) on a sptensor

    rand('state',0); %<-- Reproducible random numbers.
    A = sptensor(tensor(floor(5*rand(2,2,2)))) %<-- Create data.
    B = sptensor(tensor(floor(5*rand(2,2,2)))) %<-- Create more data.

    A is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)     4
    	(2,1,1)     1
    	(1,2,1)     3
    	(2,2,1)     2
    	(1,1,2)     4
    	(2,1,2)     3
    	(1,2,2)     2
    B is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)     4
    	(2,1,1)     2
    	(1,2,1)     3
    	(2,2,1)     3
    	(1,1,2)     4
    	(2,1,2)     3
    	(2,2,2)     2

    +A %<-- Calls uplus.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)     4
    	(2,1,1)     1
    	(1,2,1)     3
    	(2,2,1)     2
    	(1,1,2)     4
    	(2,1,2)     3
    	(1,2,2)     2

    -A %<-- Calls uminus.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)    -4
    	(2,1,1)    -1
    	(1,2,1)    -3
    	(2,2,1)    -2
    	(1,1,2)    -4
    	(2,1,2)    -3
    	(1,2,2)    -2

    A+B %<-- Calls plus.

    ans is a sparse tensor of size 2 x 2 x 2 with 8 values
    	(1,1,1)     8
    	(1,1,2)     8
    	(1,2,1)     6
    	(1,2,2)     2
    	(2,1,1)     3
    	(2,1,2)     6
    	(2,2,1)     5
    	(2,2,2)     2

    A-B %<-- Calls minus.

    ans is a sparse tensor of size 2 x 2 x 2 with 4 values
    	(1,2,2)     2
    	(2,1,1)    -1
    	(2,2,1)    -1
    	(2,2,2)    -2

    A.*B %<-- Calls times.

    ans is a sparse tensor of size 2 x 2 x 2 with 6 values
    	(1,1,1)    16
    	(1,1,2)    16
    	(1,2,1)     9
    	(2,1,1)     2
    	(2,1,2)     9
    	(2,2,1)     6

    5*A %<-- Calls mtimes.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)    20
    	(1,1,2)    20
    	(1,2,1)    15
    	(1,2,2)    10
    	(2,1,1)     5
    	(2,1,2)    15
    	(2,2,1)    10

    A./2 %<-- Calls rdivide.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)    2.0000
    	(1,1,2)    2.0000
    	(1,2,1)    1.5000
    	(1,2,2)    1.0000
    	(2,1,1)    0.5000
    	(2,1,2)    1.5000
    	(2,2,1)    1.0000

Elementwise divsion by another sptensor is allowed, but if the sparsity pattern of the denominator should be a superset of the numerator.

    A./(A+B) %<-- Calls rdivide.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)    0.5000
    	(1,1,2)    0.5000
    	(1,2,1)    0.5000
    	(1,2,2)    1.0000
    	(2,1,1)    0.3333
    	(2,1,2)    0.5000
    	(2,2,1)    0.4000

    A./B %<-- Uh-oh. Getting a divide by zero.

    ans is a sparse tensor of size 2 x 2 x 2 with 7 values
    	(1,1,1)    1.0000
    	(1,1,2)    1.0000
    	(1,2,1)    1.0000
    	(1,2,2)       Inf
    	(2,1,1)    0.5000
    	(2,1,2)    1.0000
    	(2,2,1)    0.6667

## Use permute to reorder the modes of a sptensor

    rand('state',0); %<-- Reproducible random numbers.
    A = sptensor(@rand,[30 40 20 1], 5) %<-- Create data.

    A is a sparse tensor of size 30 x 40 x 20 x 1 with 5 values
    	( 7,19,16,1)    0.0579
    	(15,33,15,1)    0.3529
    	(19, 1,19,1)    0.8132
    	(27,18, 4,1)    0.0099
    	(29,31,13,1)    0.1389

    permute(A,[4 3 2 1]) %<-- Reorder the modes.

    ans is a sparse tensor of size 1 x 20 x 40 x 30 with 5 values
    	(1,16,19, 7)    0.0579
    	(1,15,33,15)    0.3529
    	(1,19, 1,19)    0.8132
    	(1, 4,18,27)    0.0099
    	(1,13,31,29)    0.1389

Permute works correctly for a 1-dimensional sptensor.

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor(@rand,40,4) %<-- Create data.

    X is a sparse tensor of size 40 with 4 values
    	(10)    0.8913
    	(20)    0.7621
    	(25)    0.4565
    	(39)    0.0185

    permute(X,1) %<-- Permute.

    ans is a sparse tensor of size 40 with 4 values
    	(10)    0.8913
    	(20)    0.7621
    	(25)    0.4565
    	(39)    0.0185

## Displaying a tensor

The function `disp` handles small and large elements appropriately, as well as aligning the indices.

    rand('state',0); %<-- Reproducible random numbers.
    X = sptensor([1 1 1]); %<-- Create an empty sptensor.
    X(1,1,1) = rand(1)*1e15; %<-- Insert a very big element.
    X(4,3,2) = rand(1)*1e-15; %<-- Insert a very small element.
    X(2,2,2) = rand(1); %<-- Insert a 'normal' element.
    disp(X)

    ans is a sparse tensor of size 4 x 3 x 2 with 3 values
       1.0e+14 *
    	(1,1,1)    9.5013
    	(4,3,2)    0.0000
    	(2,2,2)    0.0000

## Creating an incomplete sptensor

An incomplete sptensor is created in the same way as a sparse sptensor, but the `type` flag is set to `'incomplete'`. The values of the missing elements are unknown. The size of the incomplete sptensor is the size of the largest subscript in each dimension.

    subs = [1,1,1;2,2,2;3,4,2]; %<-- Subscripts of the known entries.
    vals = [1; 2; 0]; %<-- The values of the known entries.
    X = sptensor(subs,vals,[],[],'incomplete') %<-- Creates an incomplete sptensor.

    X is a incomplete tensor of size 3 x 4 x 2 with 3 values
    	(1,1,1)     1
    	(2,2,2)     2
    	(3,4,2)     0

The size can be specified explicitly if it is different from the max coordinates in each mode.

    X = sptensor(subs,vals,[3 5 2],[],'incomplete') %<-- Specify the size.

    X is a incomplete tensor of size 3 x 5 x 2 with 3 values
    	(1,1,1)     1
    	(2,2,2)     2
    	(3,4,2)     0

## Functions that work differently for 'incomplete' sptensors

- `double` returns a dense array with NaN for the missing entries.
- `full` returns a dense tensor with NaN for the missing entries.

## Functions not defined for 'incomplete' sptensors

The following functions are not defined for incomplete sptensors:

- `and`, `not`, `or`, `xor`
- `contract`
- `eq`, `ne`
- `fibers`
- `ge`, `gt`, `le`, `lt`
- `innerprod`
- `minus`, `plus`
- `ldivide`, `mldivide`, `mrdivide`, `mtimes`, `rdivide`, `times`
- `mttkrp`, `ttm`, `ttt`, `ttv`
- `nvecs`
- `rrf`
- `spmatrix`