%% How to Create a Faust
%
%% 1. Setting the Factors Manually
%
% Let's start by creating a Faust manually, that is factor by factor.
% Below is a creation of a Faust containing 5 factors, alternating sparse and dense factors

import matfaust.Faust
factors = cell(1,5);
is_sparse = false;
for i=1:5
        if(is_sparse) % odd index factors are sparse matrices
                factors{i} = sprand(100, 100, 0.1);
        else % even index gives a dense matrix
                factors{i} = rand(100, 100);
        end
        is_sparse = ~ is_sparse;     
end
% define a Faust with those factors
F = Faust(factors)

% As you noticed, the Faust output contains the list of factors and their features but also a header describing the Faust operator itself: its size, its density, the number of nonzeros it contains (nnz_sum) along with all its factors.
% You can also call disp(F) to get all the information.

disp(F)

% Note that when you don't need F anymore, you can delete it with the instruction delete(F) or clear F.  Normally, that's the role of the garbage collector but it might happen that your Faust is very eager in memory and a manual deletion is necessary.
%% 2. Faust File Loading
%
% It's really handy to create a Faust and retrieve it from a file later. Let's see in the code below how to proceed.
% First save the Faust.

save(F, 'F.mat')

% Now let's get it back from file.

file_F = Faust('F.mat')

% The file storage format used is matlab v7. This format allows the compatibility between matfaust and pyfaust, the Python wrapper. You can easily reload the F.mat file from pyfaust.
%
%% 3. Generating a Random Faust
%
% The matfaust package provides functions for generating Faust objects by many manners. One noticeable function of this package is rand(). This function allows to generate a random Faust satisfying certain constraints; the number of factors, the size of these factors, the density, the scalar type, etc.
% Below are examples of (pseudo-)random generations.

F = matfaust.rand(10, 10, 'num_factors', 2, 'density', .5, 'field', 'complex')

% F is a complex Faust. Its rate of nonzeros, for each factor, is about 0.5. Since the fac_type argument is not set, each factor is sparse.

G = matfaust.rand(14, 20, 'num_factors', [2, 5], 'dim_sizes', [14, 20], 'density', .5, 'fac_type', 'dense')

% G is a real Faust (the default scalar type is double). In the rand() call num_factors value  ([2, 5]) defines the bounds in which we want the number of factors to be and likewise the dim_sizes argument defines the bounds in which to randomly choose the sizes of the two dimensions of each intermediary factor composing the Faust. The sizes are chosen to keep G consistent though, this is a matrix product!
% The rand() function will surely be of a great help if you want to test the Faust member functions. A second notebook might guide you in this road: How to Manipulate a Faust.
%% 4. Other Ways of Creation
% There exist many ways to create a Faust, please look at the package documentation for more information. It would be the topic of another notebook! If you want, for example, to learn about Faust generation based on the FAµST's factorization algorithms, check this notebook: Using the FAµST Factorization Wrappers.
% Note: this livescript was executed using the following matfaust version:

matfaust.version()