%Ekta Gujral,Ravdeep Pasricha and Evangelos E. Papalexakis
%Department of Computer Science and Engineering, University of California Riverside 
%"OCTen:Online Compression-based Tensor Decomposition", Submitted in PKDD 2018
clear all;close all;clc;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%To run this code we need supporting code : http://www.telecom.tuc.gr/~nikos/comfac.m
%Following lines automatically download the code for you.

url = 'http://www.telecom.tuc.gr/~nikos/comfac.m';
urlwrite(url, 'comfac.m');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% load data
load('Syndata/X_100.mat')
I=size(X,1);J=size(X,2);K=size(X,3);
%% Parameter Intilization
ops.R = 5;
ops.ratio=0.1;
ops.Q=30;
ops.p=20;
ops.shared=5;
ops.batchsize=ops.ratio*K;
k = round(ops.ratio*K);
cnt=0; timeSpent=0;MemSpent=0;
 parpool('local',2) % we set it to 20 for our experiments
%% initilize summaries from old data and get results
% Get initial decomposition, summaries and compression matrix from first
% few slices of tensor X and save time spent for decomposition
disp('Decomposition Xold tensor');
X_old=X(:,:,1:k);

st=tic;
[A_old,B_old,C_old,U,V,summaries]=OCTen_initilization(X_old,ops);
finshTime=toc(st);
timeSpent(1)=finshTime;
mem_elements = evalin('base','whos'); 
for i = 1:size(mem_elements,1) 
if strcmp(mem_elements(i).name,'summaries')==1
    initmem=mem_elements(i).bytes/1048576;
end
end
         MemSpent(1)=initmem;
% normalize the data to preserve original nature and save it in cell array
          A_old=normalizeMatrix(A_old,ops.R);
          B_old=normalizeMatrix(B_old,ops.R);  
          C_old=getTemporalMatrix(double(X_old),A_old,B_old,C_old,1);
          Factmat{1}=A_old;Factmat{2}=B_old;Factmat{3}=C_old;
          Xinc=ktensor(ones(ops.R,1),A_old,B_old,C_old);
          fitness(1)=1-norm(tensor(X_old)-tensor(Xinc))/norm(tensor(X_old));
          % incremental decomposition starts here
           totalMem=0;it=0;
 for i = k+1:ops.batchsize:K
     it=it+1;
     fprintf('Slice number: %d\n',i);
     if(i+ops.batchsize-1 > K)
        ops.batchsize=(K-i+1); % help in case last slice size is less than batchsize/
     end
     % create tensor from new slices.
       X_new_slice=X(:,:,i:i+ops.batchsize-1);
       summaries_old=summaries;
     % start here  
       st=tic;
       [A,B,C,summaries,memUsed]=OCTen_update(X_new_slice,summaries_old,ops,U,V);
       ft=toc(st); finshTime=finshTime+ft; totalMem=(memUsed/1048576); % mem/1048576 convert it to MBs
       Xinc=ktensor(ones(ops.R,1),A,B,C);
       fitness(it+1)=1-norm(tensor(X_new_slice)-tensor(Xinc))/norm(tensor(X));
       MemSpent(it+1)=totalMem;timeSpent(it+1)=ft ;
      % end here

      % Following is optional if need to add rows in C matrix.
      % Update temporal and non temporal factor matrices with its correct permutaion 
      % based on previous results and stack C matrices also.
       [A,pmA]=perm2match(normalizeMatrix(A,ops.R),A_old);
       [B,~]=perm2match(normalizeMatrix(B,ops.R),B_old);
       [C]=getTemporalMatrix(X_new_slice,A,B,C,pmA);
       Factmat{1}=A;Factmat{2}=B;Factmat{3}=[Factmat{3};C];
 end
 
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   delete 'comfac.m'
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    clc;
    disp('Checking fitness of results')
   %% evaluate results
    Xinc=ktensor(ones(ops.R,1),Factmat{1},Factmat{2},Factmat{3});
    FitX=1-norm(tensor(X)-tensor(Xinc))/norm(tensor(X));
    fprintf('Fitness, Finish time (2-workers) , memory used \n');     
    fprintf(' %f, %f, %f \n', 100*FitX,finshTime,totalMem);
    fprintf('NOTE: For our experiments we use 20-workers\n');
   delete(gcp('nocreate'))
%% plot per slice fitness
disp('Displaying results')
subplot(1,3,1)
plot(100*fitness(2:end),'Linewidth',3)
ylim([50 102])
xlabel('Iteration')
ylabel('Fitness (%)')

subplot(1,3,2)
plot(timeSpent(2:end),'Linewidth',3)
ylim([0 max(timeSpent(2:end))+1])
xlabel('K')
ylabel('CPU Time(seconds)')

subplot(1,3,3)
plot( MemSpent(2:end),'Linewidth',3)
xlabel('K')
ylabel('Memory (MB)')
suptitle('NOTE: For our experiments we use 20-workers. These results are with 2-workers')
delete(gcp('nocreate'))