%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  MATLAB Code for                                                  %
%                                                                   %
%  Multi-Objective Particle Swarm Optimization (MOPSO)              %
%  Version 1.0 - Feb. 2011                                          %
%                                                                   %
%  According to:                                                    %
%  Carlos A. Coello Coello et al.,                                  %
%  "Handling Multiple Objectives with Particle Swarm Optimization," %
%  IEEE Transactions on Evolutionary Computation, Vol. 8, No. 3,    %
%  pp. 256-279, June 2004.                                          %
%                                                                   %
%  Developed Using MATLAB R2009b (Version 7.9)                      %
%                                                                   %
%  Programmed By: S. Mostapha Kalami Heris                          %
%                                                                   %
%         e-Mail: sm.kalami@gmail.com                               %
%                 kalami@ee.kntu.ac.ir                              %
%                                                                   %
%       Homepage: http://www.kalami.ir                              %
%                                                                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function pop=DetermineDomination(pop)

    npop=numel(pop);

    for i=1:npop
        pop(i).Dominated=false;
        for j=1:i-1
            if ~pop(j).Dominated
                if Dominates(pop(i),pop(j))
                    pop(j).Dominated=true;
                elseif Dominates(pop(j),pop(i))
                    pop(i).Dominated=true;
                    break;
                end
            end
        end
    end

end


function [wedge_data wedge_density] = wedge();

% wedge coordinates
Y = [-7.0 -4.35    0  3.0  0 -4.35 -7.0 -7.0];
Z = [-5.8 -5.8  -2.46    0  0   0    0  -5.8];
figure; line(Y,Z, 'LineStyle', '-', 'Marker', 'o');
disp('This wedge can be modeled as a rectangle and a triangle, as shown below')
Y = [-7.0 -4.35   -4.35 -7.0 -7.0];
Z = [-5.8 -5.8  0    0  -5.8];
figure; line(Y,Z, 'Color', 'b', 'LineStyle', '-', 'Marker', 'o');
Y = [-4.35  3.0  -4.35 -4.35];
Z = [-5.8    0     0   -5.8];
hold on; line(Y,Z, 'Color', 'r', 'LineStyle', '-', 'Marker', 'o'); axis equal;
xlabel('Y/cm'); ylabel('Z/cm'); title('Elekta Universal Wedge');

% From the NIST website, get the attenuation coefficients.
% Components of the wedge:
Pb = 0.96     %Fraction by weigth for Lead
Sb = 0.04     %Fraction by weight for Antimony

% Ref:
%http://physics.nist.gov/PhysRefData/XrayMassCoef/ElemTab/z82.html
%Energy       mu over rho        mu e n over rho
%      (MeV)      (cm2/g)     (cm2/g)
%____________________________________
%
Pb_data =   [1.00000E-03  5.210E+03  5.197E+03
   1.50000E-03  2.356E+03  2.344E+03
   2.00000E-03  1.285E+03  1.274E+03
   2.48400E-03  8.006E+02  7.895E+02
   2.48400E-03  1.397E+03  1.366E+03
   2.53429E-03  1.726E+03  1.682E+03
   2.58560E-03  1.944E+03  1.895E+03
   2.58560E-03  2.458E+03  2.390E+03
   3.00000E-03  1.965E+03  1.913E+03
   3.06640E-03  1.857E+03  1.808E+03
   3.06640E-03  2.146E+03  2.090E+03
   3.30130E-03  1.796E+03  1.748E+03
   3.55420E-03  1.496E+03  1.459E+03
   3.55420E-03  1.585E+03  1.546E+03
   3.69948E-03  1.442E+03  1.405E+03
   3.85070E-03  1.311E+03  1.279E+03
   3.85070E-03  1.368E+03  1.335E+03
   4.00000E-03  1.251E+03  1.221E+03
   5.00000E-03  7.304E+02  7.124E+02
   6.00000E-03  4.672E+02  4.546E+02
   8.00000E-03  2.287E+02  2.207E+02
   1.00000E-02  1.306E+02  1.247E+02
   1.30352E-02  6.701E+01  6.270E+01
   1.30352E-02  1.621E+02  1.291E+02
   1.50000E-02  1.116E+02  9.100E+01
   1.52000E-02  1.078E+02  8.807E+01
   1.52000E-02  1.485E+02  1.131E+02
   1.55269E-02  1.416E+02  1.083E+02
   1.58608E-02  1.344E+02  1.032E+02
   1.58608E-02  1.548E+02  1.180E+02
   2.00000E-02  8.636E+01  6.899E+01
   3.00000E-02  3.032E+01  2.536E+01
   4.00000E-02  1.436E+01  1.211E+01
   5.00000E-02  8.041E+00  6.740E+00
   6.00000E-02  5.021E+00  4.149E+00
   8.00000E-02  2.419E+00  1.916E+00
   8.80045E-02  1.910E+00  1.482E+00
   8.80045E-02  7.683E+00  2.160E+00
   1.00000E-01  5.549E+00  1.976E+00
   1.50000E-01  2.014E+00  1.056E+00
   2.00000E-01  9.985E-01  5.870E-01
   3.00000E-01  4.031E-01  2.455E-01
   4.00000E-01  2.323E-01  1.370E-01
   5.00000E-01  1.614E-01  9.128E-02
   6.00000E-01  1.248E-01  6.819E-02
   8.00000E-01  8.870E-02  4.644E-02
   1.00000E+00  7.102E-02  3.654E-02
   1.25000E+00  5.876E-02  2.988E-02
   1.50000E+00  5.222E-02  2.640E-02
   2.00000E+00  4.606E-02  2.360E-02
   3.00000E+00  4.234E-02  2.322E-02
   4.00000E+00  4.197E-02  2.449E-02
   5.00000E+00  4.272E-02  2.600E-02
   6.00000E+00  4.391E-02  2.744E-02
   8.00000E+00  4.675E-02  2.989E-02
   1.00000E+01  4.972E-02  3.181E-02
   1.50000E+01  5.658E-02  3.478E-02
   2.00000E+01  6.206E-02  3.595E-02];

%Antimony
%Z = 51
%
%ASCII format
%
%____________________________________
%
%     Energy       mu over rho        mu e n over rho
%      (MeV)      (cm2/g)     (cm2/g)
%____________________________________

Sb_data = [1.00000E-03  8.582E+03  8.568E+03
   1.50000E-03  3.491E+03  3.481E+03
   2.00000E-03  1.767E+03  1.759E+03
   3.00000E-03  6.536E+02  6.469E+02
   4.00000E-03  3.169E+02  3.113E+02
   4.13220E-03  2.918E+02  2.863E+02
   4.13220E-03  8.691E+02  8.252E+02
   4.25449E-03  8.308E+02  7.865E+02
   4.38040E-03  7.776E+02  7.392E+02
   4.38040E-03  1.050E+03  9.906E+02
   4.53657E-03  9.743E+02  9.178E+02
   4.69830E-03  8.939E+02  8.457E+02
   4.69830E-03  1.029E+03  9.725E+02
   5.00000E-03  8.846E+02  8.377E+02
   6.00000E-03  5.569E+02  5.305E+02
   8.00000E-03  2.631E+02  2.518E+02
   1.00000E-02  1.459E+02  1.396E+02
   1.50000E-02  4.923E+01  4.657E+01
   2.00000E-02  2.268E+01  2.105E+01
   3.00000E-02  7.631E+00  6.755E+00
   3.04912E-02  7.307E+00  6.452E+00
   3.04912E-02  4.073E+01  1.391E+01
   4.00000E-02  2.027E+01  9.789E+00
   5.00000E-02  1.120E+01  6.400E+00
   6.00000E-02  6.879E+00  4.311E+00
   8.00000E-02  3.176E+00  2.173E+00
   1.00000E-01  1.758E+00  1.237E+00
   1.50000E-01  6.361E-01  4.312E-01
   2.00000E-01  3.381E-01  2.084E-01
   3.00000E-01  1.677E-01  8.504E-02
   4.00000E-01  1.172E-01  5.288E-02
   5.00000E-01  9.453E-02  4.061E-02
   6.00000E-01  8.153E-02  3.465E-02
   8.00000E-01  6.670E-02  2.896E-02
   1.00000E+00  5.797E-02  2.608E-02
   1.25000E+00  5.086E-02  2.378E-02
   1.50000E+00  4.628E-02  2.230E-02
   2.00000E+00  4.105E-02  2.081E-02
   3.00000E+00  3.686E-02  2.043E-02
   4.00000E+00  3.567E-02  2.118E-02
   5.00000E+00  3.559E-02  2.219E-02
   6.00000E+00  3.598E-02  2.321E-02
   8.00000E+00  3.745E-02  2.509E-02
   1.00000E+01  3.921E-02  2.664E-02
   1.50000E+01  4.351E-02  2.920E-02
   2.00000E+01  4.704E-02  3.038E-02];

% put data on the same, unique intervals.
[A, s] = unique(Pb_data(:,1));
[B,I] = unique(Sb_data(:,1));
Pb_data = [B interp1(Pb_data(s,1), Pb_data(s,2), B) interp1(Pb_data(s,1), Pb_data(s,3), B)];
Sb_data = [B interp1(Sb_data(I,1), Sb_data(I,2), B) interp1(Sb_data(I,1), Sb_data(I,3), B)];

wedge_data = Pb*Pb_data + Sb*Sb_data;
figure; loglog(Pb_data(:,1), Pb_data(:,2), Sb_data(:,1), Sb_data(:,2), wedge_data(:,1), wedge_data(:,2));
wedge_density = 11.16;


function [g1,g2] = sdlfmaXsdrbfKernGradient(sdlfmaKern, sdrbfKern, t1, ...
    t2, covGrad)

% SDLFMAXSDRBFKERNGRADIENT Gradients cross kernel between a SDLFM and SDRBF
% FORMAT
% DESC computes a cross gradient for a cross kernel between a switching
% dynamical LFM kernel (accel.) and a switching dynamical RBF kernel.
% ARG sdlfmvKern : the kernel structure associated with the SDLFM
% kernel (acceleration).
% ARG sdrbfKern : the kernel structure associated with the SDRBF kernel.
% ARG t1 : inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see lfmKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see lfmKernExtractParam.
%
% FORMAT
% DESC computes a cross gradient for a cross kernel between a switching
% dynamical LFM kernel (accel.) and a switching dynamical RBF kernel.
% ARG sdlfmvKern : the kernel structure associated with the SDLFM
% kernel (acceleration).
% ARG sdrbfKern : the kernel structure associated with the SDRBF kernel.
% ARG t1 : row inputs for which kernel is to be computed.
% ARG t2 : column inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see lfmKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see lfmKernExtractParam.
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

if nargin == 4
    covGrad = t2;
    t2 = t1;
end

[g1, g2] = sdlfmXsdrbfKernGradient(sdlfmaKern, sdrbfKern, t1, t2, covGrad, 'Accel');


 classdef FGaussDiscontinuousFunction < handle
    % nDimf * nGaus * nElem
    properties (Constant, Access = public)
        fType = 'GAUSSPOINTS'
    end

    properties (Access = public)
        ndimf
        fValues
        quadrature
    end

    properties (Access = private)
        mesh
    end

    properties (Access = private)
    end

    methods (Access = public)

        function obj = FGaussDiscontinuousFunction(cParams)
            obj.init(cParams)
        end

        function fxV = evaluate(obj, xV)
            assert(isequal(xV, obj.quadrature.posgp), 'Gauss points do not match')
            fxV = obj.fValues;
        end

        function dNdx  = computeCartesianDerivatives(obj, quad)
            assert(isequal(quad,obj.quadrature), 'Quadrature does not match');
            nElem = size(obj.mesh.connec,1);
            nNode = obj.mesh.interpolation.nnode;
            nDime = obj.mesh.interpolation.ndime;
            nGaus = quad.ngaus;
            invJ  = obj.mesh.computeInverseJacobian(quad,obj.mesh.interpolation);
            dShapeDx  = zeros(nDime,nNode,nElem,nGaus);
            for igaus = 1:nGaus
                dShapes = obj.mesh.interpolation.deriv(:,:,igaus);
                for jDime = 1:nDime
                    invJ_JI   = invJ(:,jDime,:,igaus);
                    dShape_KJ = dShapes(jDime,:);
                    dSDx_KI   = bsxfun(@times, invJ_JI,dShape_KJ);
                    dShapeDx(:,:,:,igaus) = dShapeDx(:,:,:,igaus) + dSDx_KI;
                end
            end
            dNdx = dShapeDx;
        end

        function applyVoigtNotation(obj)
            switch obj.ndimf
                case 4
                    obj.applyVoigt2D()
                case 9
                    obj.applyVoigt3D()
            end
        end

        function plot(obj)
            s.mesh = obj.mesh;
            proj = Projector_toP1(s);
            p1fun = proj.project(obj);
            p1fun.plot();
        end

        function print(obj, s)
            s.mesh = obj.mesh;
            s.fun  = {obj};
            p = FunctionPrinter(s);
            p.print();
        end

        function [res, pformat] = getDataToPrint(obj)
            nElem = size(obj.fValues, 3);
            nGaus = obj.quadrature.ngaus;
            s.nDimf   = obj.ndimf;
            s.nData   = nElem*nGaus;
            s.nGroup  = nElem;
            s.fValues = obj.getFormattedFValues();
            fps = FunctionPrintingSettings(s);
            [res, pformat] = fps.getDataToPrint();
        end

        function dofConnec = computeDofConnectivity(obj)
            % This assumes that FGaussDiscFun comes from a P1Fun...
            conne  = obj.mesh.connec;
            nDimf  = obj.ndimf;
            nNode  = size(conne, 2);
            nDofsE = nNode*nDimf;
            dofsElem  = zeros(nDofsE,size(conne,1));
            for iNode = 1:nNode
                for iUnkn = 1:nDimf
                    idofElem   = nDimf*(iNode - 1) + iUnkn;
                    globalNode = conne(:,iNode);
                    idofGlobal = nDimf*(globalNode - 1) + iUnkn;
                    dofsElem(idofElem,:) = idofGlobal;
                end
            end
            dofConnec = dofsElem;
        end

    end

    methods (Access = private)

        function init(obj,cParams)
            obj.fValues    = cParams.fValues;
            obj.quadrature = cParams.quadrature;
            obj.ndimf      = size(cParams.fValues,1);
            obj.mesh       = cParams.mesh;
        end

        function applyVoigt2D(obj)
            nGaus = obj.quadrature.ngaus;
            nElem = size(obj.fValues,3);
            fV(1,:,:) = obj.fValues(1,:,:); % xx
            fV(2,:,:) = obj.fValues(4,:,:); % yy
            fV(3,:,:) = obj.fValues(2,:,:) + obj.fValues(3,:,:); % xy
            fV = reshape(fV, [3 nGaus nElem]);
            obj.fValues = fV;
            obj.ndimf = 3;
        end

        function applyVoigt3D(obj)
            nGaus = obj.quadrature.ngaus;
            nElem = size(obj.fValues,3);
            fV(1,:,:) = obj.fValues(1,:,:); % xx
            fV(2,:,:) = obj.fValues(5,:,:); % yy
            fV(3,:,:) = obj.fValues(9,:,:); % zz
            fV(4,:,:) = obj.fValues(2,:,:) + obj.fValues(4,:,:); % xy
            fV(5,:,:) = obj.fValues(3,:,:) + obj.fValues(7,:,:); % xz
            fV(6,:,:) = obj.fValues(6,:,:) + obj.fValues(8,:,:); % yz
            fV = reshape(fV, [6 nGaus nElem]);
            obj.fValues = fV;
            obj.ndimf = 6;
        end

        % Printing
        function fM = getFormattedFValues(obj)
            fV = obj.fValues;
            nGaus = obj.quadrature.ngaus;
            nComp = obj.ndimf;
            nElem = size(obj.fValues, 3);
            fM  = zeros(nGaus*nElem,nComp);
            for iStre = 1:nComp
                for iGaus = 1:nGaus
                    rows = linspace(iGaus,(nElem - 1)*nGaus + iGaus,nElem);
                    fM(rows,iStre) = fV(iStre,iGaus,:);
                end
            end
        end

    end

end


maxepoch=5;
fprintf(1,'\nFine-tuning deep autoencoder by minimizing cross entropy error. \n');

load batchdata
load mnistvh
load mnisthp
load mnisthp2
load mnistpo

[numcases numdims numbatches]=size(batchdata);
w1=[vishid; hidrecbiases];
w2=[hidpen; penrecbiases];
w3=[hidpen2; penrecbiases2];
w4=[hidtop; toprecbiases];
w5=[hidtop'; topgenbiases];
w6=[hidpen2'; hidgenbiases2];
w7=[hidpen'; hidgenbiases];
w8=[vishid'; visbiases];
l1=size(w1,1)-1;
l2=size(w2,1)-1;
l3=size(w3,1)-1;
l4=size(w4,1)-1;
l5=size(w5,1)-1;
l6=size(w6,1)-1;
l7=size(w7,1)-1;
l8=size(w8,1)-1;
l9=l1;

for epoch = 1:maxepoch
    tt=0;
    for batch = 1:numbatches/10
        fprintf(1,'epoch %d batch %d\r',epoch,batch);
        tt=tt+1;
        data=[];
        for kk=1:10
            data=[data
                batchdata(:,:,(tt-1)*10+kk)];
        end
        max_iter=3;
        VV = [w1(:)' w2(:)' w3(:)' w4(:)' w5(:)' w6(:)' w7(:)' w8(:)']';
        Dim = [l1; l2; l3; l4; l5; l6; l7; l8; l9];

        [X, fX] = minimize(VV,'CG_MNIST',max_iter,Dim,data);

        w1 = reshape(X(1:(l1+1)*l2),l1+1,l2);
        xxx = (l1+1)*l2;
        w2 = reshape(X(xxx+1:xxx+(l2+1)*l3),l2+1,l3);
        xxx = xxx+(l2+1)*l3;
        w3 = reshape(X(xxx+1:xxx+(l3+1)*l4),l3+1,l4);
        xxx = xxx+(l3+1)*l4;
        w4 = reshape(X(xxx+1:xxx+(l4+1)*l5),l4+1,l5);
        xxx = xxx+(l4+1)*l5;
        w5 = reshape(X(xxx+1:xxx+(l5+1)*l6),l5+1,l6);
        xxx = xxx+(l5+1)*l6;
        w6 = reshape(X(xxx+1:xxx+(l6+1)*l7),l6+1,l7);
        xxx = xxx+(l6+1)*l7;
        w7 = reshape(X(xxx+1:xxx+(l7+1)*l8),l7+1,l8);
        xxx = xxx+(l7+1)*l8;
        w8 = reshape(X(xxx+1:xxx+(l8+1)*l9),l8+1,l9);
    end
    savepath=['.\data\mnist_weights' num2str(j) num2str(i)];
    save(savepath, 'w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'vishid', 'hidrecbiases', 'visbiases', 'hidpen', 'penrecbiases', 'hidgenbiases', 'hidpen2', 'penrecbiases2', 'hidgenbiases2', 'hidtop', 'toprecbiases', 'topgenbiases');
end
%


function varargout = drawPolygon3d(varargin)
%DRAWPOLYGON3D Draw a 3D polygon specified by a list of vertex coords.
%
%   drawPolygon3d(POLY);
%   packs coordinates in a single N-by-3 array.
%
%   drawPolygon3d(PX, PY, PZ);
%   specifies coordinates in separate numeric vectors (either row or
%   columns)
%
%   drawPolygon3d(..., PARAM, VALUE);
%   Specifies style options to draw the polyline, see plot for details.
%
%   H = drawPolygon3d(...);
%   also returns a handle to the list of created line objects.
%
%   Example
%     t = linspace(0, 2*pi, 100)';
%     xt = 10 * cos(t);
%     yt = 5 * sin(t);
%     zt = zeros(1,100);
%     figure; drawPolygon3d(xt, yt, zt, 'b');
%
%   See Also:
%   polygons3d, fillPolygon3d, drawPolyline3d
%

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2011-08-17 from drawPolyline3d, using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% HISTORY
% 2019-02-02 add support for multiple polygons

%% Process input arguments

% extract handle of axis to draw on
ax = gca;
var1 = varargin{1};
if isAxisHandle (var1)
    ax          = var1;
    varargin(1) = [];
end

% check case we want to draw several curves, stored in a cell array
var1 = varargin{1};
if iscell(var1)
    hold on;
    h = [];
    for i = 1:length(var1(:))
        h = [h; drawPolygon3d(ax, var1{i}, varargin{2:end})]; %#ok<AGROW>
    end
    if nargout > 0
        varargout{1} = h;
    end
    return;
end

%% extract polygon coordinates
if min(size(var1)) == 1
    % if first argument is a vector (either row or column), then assumes
    % first argument contains x coords, second argument contains y coords
    % and third one the z coords
    px = var1;
    if length(varargin) < 3
        error('geom3d:drawPolygon3d:Wrong number of arguments in fillPolygon3d');
    end
    py = varargin{2};
    pz = varargin{3};
    varargin = varargin(4:end);
else
    % first argument contains both coordinate
    px = var1(:, 1);
    py = var1(:, 2);
    pz = var1(:, 3);
    varargin = varargin(2:end);
end

%% draw the polygon

% check that the polygon is closed
if px(1) ~= px(end) || py(1) ~= py(end) || pz(1) ~= pz(end)
    px = [px(:); px(1)];
    py = [py(:); py(1)];
    pz = [pz(:); pz(1)];
end

% draw the closed curve
h = plot3(ax, px, py, pz, varargin{:});

%% Format output

if nargout > 0
    varargout = {h};
end


function B = repelm(A,varargin)
%REPELM Replicate elements in an array.
%
%   REPELM(A,M,N) and REPELM(A,[M N]) replicates each element in the matrix
%   A so it becomes an M-by-N matrix.
%
%   REPELM(A,M,N,P,...) and REPELM(A,[M N P ...]) replicates each element in
%   A so it becomes an M-by-N-by-P-by-... array.  A can be N-D.
%
%   REPELM(A,M,N) when A is a matrix is the same as KRON(A,ONES(M,N)), but
%   the former is much faster since it does no multiplications.  The former
%   also works when A is not of class double.
%
%   Example:
%       repelm(magic(2),2,3)
%       repelm(NaN,2,3)
%
%   See also REPMAT, MESHGRID, NDGRID.

%   Author:      Peter J. Acklam
%   Time-stamp:  2002-03-03 13:21:10 +0100
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

if nargin < 2
   error( 'Not enough input arguments.' );
elseif nargin == 2
   if length(varargin{1}) == 1          % REPELM(A,M)
      siz = [ varargin{1} varargin{1} ];
   else                                 % REPELM(A,[M N P ...])
      siz = varargin{1};
   end
else                                    % REPELM(A,M,N,P,...)
   siz = [ varargin{:} ];
end

if length(A) == 1
   nelems = prod(siz);
   if nelems > 0
      % Since B doesn't exist, the first statement creates a B with
      % the right size and type.  Then use scalar expansion to
      % fill the array.  Finally reshape to the specified size.
      B(nelems) = A;
      B(:) = A;
      B = reshape(B,siz);
   else
      B = A(ones(siz));
   end
elseif ndims(A)==2 & length(siz)==2
   [m,n] = size(A);
   mind = 1:m;
   nind = 1:n;
   mind = mind(ones(1,siz(1)),:);
   nind = nind(ones(1,siz(2)),:);
   B = A(mind,nind);
else

%   Asiz = size(A);
%   Asiz = [Asiz ones(1,length(siz)-length(Asiz))];
%   siz = [siz ones(1,length(Asiz)-length(siz))];
%   for i = 1:length(Asiz)
%      ind = 1:Asiz(i);
%      subs{i} = ind(ones(1,siz(i)),:);
%   end
%   B = A(subs{:});

   Asiz = size(A);
   Adim = length(Asiz);
   Rdim = length(siz);
   Bdim = max(Adim, Rdim);
   Asiz  = [Asiz ones(1,Bdim-Adim)];
   subs = {':'};
   subs = subs(ones(1,Bdim));
   for i = 1:Rdim
      if siz(i) > 1
         ind = 1:Asiz(i);
         subs{i} = ind(ones(1,siz(i)),:);
      end
   end
   B = A(subs{:});

end


function varargout = fevalm(f, r, lambda, theta)
%FEVAL   Evaluate a BALLFUNV
%   FEVAL(F, R, L, T) evaluates a BALLFUNV F at the points (R,L,T) in spherical coordinates
%   at a tensor-product grid R x L x T.
%
% See also SUBSREF.

% Copyright 2019 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

if isempty( f )
    varargout = {};
    return
end

F = f.comp;

% Evaluate at the tensor grid
valsX = fevalm(F{1}, r, lambda, theta);
valsY = fevalm(F{2}, r, lambda, theta);
valsZ = fevalm(F{3}, r, lambda, theta);

varargout = {valsX, valsY, valsZ};
end


% Get vertex coordinates for the patch type 'B'
% [C, N, S, W, E] = HealpixGetPatchVertexCoordsB(n, i, j, INFO)
%
% Parameters
% n : grid resolution
% i : ring index
% j : intra-ring index
% INFO : intermediate information (output of HealpixSelectPatchClass())
% C : intra-patch coordinates
% N : coordinates for north vertex
% S : coordinates for south vertex
% W : coordinates for west vertex
% E : coordinates for east vertex

function [C, N, S, W, E] = HealpixGetPatchVertexCoordsB(n, i, j, INFO)

% gradient of the border
grad = INFO.polar_part;

decimal_i = INFO.decimal_i_n;
decimal_j = INFO.decimal_polar_intra_part;

int_i = INFO.int_i_n;

if int_i == n
    int_j = fix(j);
    if int_j == 0
        int_j = 4 * INFO.int_i_n;
    end

    north_int_j = mod(int_j - grad - 1, 4 * (n - 1)) + 1;
    east_int_j = mod(int_j + 1 - 1, 4 * n) + 1;

    N = [int_i - 1, north_int_j];
    S = [int_i + 1, int_j];
    W = [int_i    , int_j];
    E = [int_i    , east_int_j];

    offset_j = 0.5 * decimal_i;
    C = [decimal_i, decimal_j + offset_j - 0.5];
else
    int_j = fix(j - grad * decimal_i);
    if int_j == 0
        int_j = 4 * n;
    end

    west_int_j = mod(int_j + grad - 1, 4 * n) + 1;
    east_int_j = mod(west_int_j + 1 - 1, 4 * n) + 1;

    N = [int_i    , int_j];
    S = [int_i + 2, west_int_j];
    W = [int_i + 1, west_int_j];
    E = [int_i + 1, east_int_j];

    offset_j = 0.5 * (1 - decimal_i);
    C = [decimal_i - 1, decimal_j + offset_j - 0.5];
end

if INFO.is_south_pole
    TMP = N;
    N = S;
    S = TMP;
    N(1) = 4 * n - N(1);
    S(1) = 4 * n - S(1);
    W(1) = 4 * n - W(1);
    E(1) = 4 * n - E(1);
    C(1) = -C(1);
end


function [IN,JN,XN,II,JI,XI] = globMatrixIFE3D(fun,mesh,femI,fem1,d1,fem2,d2)

%% USAGE: generate global matrix on a 3D mesh
%
% INPUTS:
% fun --- coefficient function
% mesh --- a struct data contains very rich mesh information.
% fem1 --- global DoF for test function space
% fem2 --- global DoF for trial function space
% d1 --- derivative info for test function
% d2 --- derivative info for trial function
%            d = [0,0,0]: function value
%            d = [1,0,0]: Dx value
%            d = [0,1,0]: Dy value
%            d = [0,0,1]: Dz value
%
% OUTPUTS:
% [IN JN XN] --- triplets of the sparse matrix from regular elements.
% [II JI XI] --- triplets of the sparse matrix from interface elements.

% Last Modified: 08/07/2020 by Xu Zhang

%% 0. Initializaiton
if nargin == 5
    fem2 = fem1; d2 = d1;
end

if strcmp(fem1.type,'P1')||strcmp(fem1.type,'DGP1')||strcmp(fem1.type,'CR')
    feEvalBas1 = @evalP1Bas3D;
elseif strcmp(fem1.type,'P2')||strcmp(fem1.type,'DGP2')
    feEvalBas1 = @evalP2Bas3D;
end

if strcmp(fem2.type,'P1')||strcmp(fem2.type,'DGP1')||strcmp(fem2.type,'CR')
    feEvalBas2 = @evalP1Bas3D;
elseif strcmp(fem2.type,'P2')||strcmp(fem2.type,'DGP2')
    feEvalBas2 = @evalP2Bas3D;
end

%% 1. Matrix on noninterface elements
dof1 = fem1.ldof; dof2 = fem2.ldof; nloc = dof1*dof2;
ntID = find(mesh.tLoc > 0); ntN = length(ntID);
AN = fem1.area(ntID);
gxN = fem1.gx(ntID,:); gyN = fem1.gy(ntID,:); gzN = fem1.gz(ntID,:); gw = fem1.gw;
XN = zeros(nloc*ntN, 1);

coefN = feval(fun,gxN,gyN,gzN);
Ibas = cell(dof1,1); Jbas = cell(dof2,1);
for i = 1:dof1
    Ibas{i} = feEvalBas1(fem1.bas(ntID,:,i), gxN, gyN, gzN, d1);
end
for j = 1:dof2
    Jbas{j} = feEvalBas2(fem2.bas(ntID,:,j), gxN, gyN, gzN, d2);
end

IN = reshape(repmat(fem1.t(ntID,:),4,1),nloc*ntN,1);
JN = repmat(reshape(fem2.t(ntID,:),dof2*ntN,1),4,1);
ind = 0;
for i = 1:dof1
    for j = 1:dof2
        XN(ind+1:ind+ntN) = AN.*sum(((Ibas{i}.*(coefN.*Jbas{j})).*gw'),2);
        ind = ind + ntN;
    end
end

%% 2. Matrix on interface elements
AI = femI.area; gw = femI.gw; gxI = femI.gx; gyI = femI.gy; gzI = femI.gz;
ntI = size(femI.t,1); % not number of interface element, but quadrature element
XI = zeros(nloc*ntI, 1);

coefI = feval(fun,gxI,gyI,gzI);
Ibas = cell(dof1,1); Jbas = cell(dof2,1);
for i = 1:dof1
    Ibas{i} = feEvalBas1(femI.bas(:,:,i), gxI, gyI, gzI, d1);
end
for j = 1:dof2
    Jbas{j} = feEvalBas2(femI.bas(:,:,j), gxI, gyI, gzI, d2);
end

II = reshape(repmat(femI.t,4,1),nloc*ntI,1);
JI = repmat(reshape(femI.t,dof2*ntI,1),4,1);
ind = 0;
for i = 1:dof1
    for j = 1:dof2
        XI(ind+1:ind+ntI) = AI.*sum(((Ibas{i}.*(coefI.*Jbas{j})).*gw'),2);
        ind = ind + ntI;
    end
end


%% Spherical Functions
%
% The |S2Fun| toolbox is a collection of Matlab classes for numerical computations with functions on the two-dimensional sphere.
% It overloads the default commands for vectors and matrices to compute the analogous operations for functions of the given type.
% The underlying mathematical approach is accomplished via spherical harmonics which form an orthonormal basis of the square-integrable functions on the two-dimensional sphere.
%
%%
%


load -ascii mushrooms.dat
mushroomsD=mushrooms';
clear mushrooms

[N, m] = size(mushroomsD);
class = 1

%rand('state',0); randn('state',0);
%abalone = abalone(:,randperm(m));

for node = 1:N
  UNI=setdiff(unique(mushroomsD(node,:)),-9999);
  for val = 1:length(UNI)
    [I,J]=find(mushroomsD(node,:)==UNI(val));
    mushroomsD(node,J)=val;
  end
end

ns = max(mushroomsD');
seul=find(ns==1);
mushroomsD=mushroomsD(setdiff(1:N,seul),:);
[N, m] = size(mushroomsD)
ns = max(mushroomsD')

Napp = ceil(m*2/3);
Ntest = m-Napp

app  = mushroomsD(:,1:Napp);size(app)
test = mushroomsD(:,Napp+1:end);size(test)

unique(app(class,:))
unique(test(class,:))

clear mushroomsD seul UNI node I J


%DEMO_PASSGP Demonstration of PASS-GP routine for GP classification
%
%  Description
%    Here we demonstrate pass-gp routine for Gaussian Processes
%    classification. Data used is 2-dimensional toy data with Gaussian
%    bumbs defining classes. We demonstrate with both fixed and not fixed
%    sizes of active set for pass-gp.
%
%  See also PASSGP

% Copyright (c) 2013 Ville Tolvanen

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

% Generate toy data
prevstream=setrandstream(0);
[x1,x2]=meshgrid(-5:0.1:5,-5:0.1:5);
x=[x1(:) x2(:)]; x=x(randperm(size(x,1),3000),:);
y=2.*mnorm_pdf(x, [0 0], [0.5 0;0 0.5]) + mnorm_pdf(x, [3 3], [0.5 0;0 0.5]) + mnorm_pdf(x, [-3 -3], [0.5 0;0 0.5]);
y=y+mnorm_pdf(x, [3 -3], [0.5 0;0 0.5])+mnorm_pdf(x, [-3 3], [0.5 0;0 0.5]);
y=y+0.03.*randn(size(y,1),1);
y(y>0.15)=1; y(y<=0.15)=-1;

[xt1, xt2]=meshgrid(-5:0.23:5,-5:0.23:5);
xt=[xt1(:) xt2(:)];
yt=ones(size(xt,1),1);

[n, nin] = size(x);

% Define covariance and likelihood functions and create model
gpcf = gpcf_sexp();
lik=lik_probit();
gp=gp_set('lik', lik, 'cf', gpcf, 'jitterSigma2', 1e-6);

opt=optimset('TolX',1e-3,'TolFun',1e-3,'display','on');
w0=gp_pak(gp);

% fPASS-GP with fixed size of 800 points in active set and data divided to
% 10 subsets with 4 sweeps over data
start=tic;[gp, indA]=passgp(gp, x, y, 'opt', opt, 'npass', 4, 'ninit', 800, 'nsub', 10, 'display', 'on', 'fixed', 'on', 'pexc', 0.1, 'optimn', 2);time=toc(start);
tt=time;
[Eft, Varft, lpyt, Eyt, Varyt]=gp_pred(gp, x(indA,:), y(indA,:), xt, 'yt', yt);
figure, [cc,hh]=contour(reshape(xt(:,1),size(xt1,1), size(xt1,1)), reshape(xt(:,2),size(xt1,1), size(xt1,1)), reshape(exp(lpyt),size(xt1,1), size(xt1,1)), [0.1 0.9]);
clabel(cc,hh); title('Pr(y==1) (fpass-gp)')
param=gp_pak(gp);

% PASS-GP with inclusion threshold 0.65, deletion threshold 0.99, intial
% size of 400 points in active set and 3 sweeps over data.
gp=gp_unpak(gp,w0);
start=tic;[gp, indA2]=passgp(gp, x, y, 'opt', opt, 'pinc', 0.65, 'pdel', 0.99, 'npass', 3, 'ninit', 400, 'nsub', 10, 'display', 'on', 'optimn', 2);time=toc(start);
tt2=time;
[Eft2, Varft2, lpyt2, Eyt2, Varyt2]=gp_pred(gp, x(indA2,:), y(indA2,:), xt, 'yt', yt);
figure, [cc,hh]=contour(reshape(xt(:,1),size(xt1,1), size(xt1,1)), reshape(xt(:,2),size(xt1,1), size(xt1,1)), reshape(exp(lpyt2),size(xt1,1), size(xt1,1)), [0.1 0.9]);
clabel(cc,hh); title('Pr(y==1) (pass-gp)')
param2=gp_pak(gp);

% Full Gaussian Process for comparison
gp=gp_unpak(gp,w0);
opt.Display='iter';
start=tic;gp=gp_optim(gp,x,y,'opt',opt);tt3=toc;
[Eft3, Varft3, lpyt3, Eyt3, Varyt3]=gp_pred(gp, x, y, xt, 'yt', yt);
figure, [cc,hh]=contour(reshape(xt(:,1),size(xt1,1), size(xt1,1)), reshape(xt(:,2),size(xt1,1), size(xt1,1)), reshape(exp(lpyt3),size(xt1,1), size(xt1,1)), [0.1 0.9]);
clabel(cc,hh); title('Pr(y==1) (full gp)')

% Display some statistics

mlpd_fpassgp=mean(mean(lpyt,2))
time_fpassgp=mean(tt)
mlpd_passgp=mean(mean(lpyt2,2))
time_passgp=mean(tt2)
mlpd_full=mean(lpyt3)
time_full=tt3

% Plot data and active sets for both methods
figure(4), subplot(1,2,1),  plot(x(y==1,1),x(y==1,2),'or',x(y==-1,1),x(y==-1,2),'ob');
hold all; plot(x(indA,1), x(indA,2), '.k'); title('Data and active set (fpass-gp)')
legend('y=1', 'y=-1', 'Active set for fpass-gp');
subplot(1,2,2),  plot(x(y==1,1),x(y==1,2),'or',x(y==-1,1),x(y==-1,2),'ob');
hold all; plot(x(indA2,1), x(indA2,2), '.k'); title('Data and active set (pass-gp)')
legend('y=1', 'y=-1', 'Active set for pass-gp');
setrandstream(prevstream);


function pass = test_sinh( pref )

% Grab some preferences
if ( nargin == 0 )
    pref = chebfunpref();
end
tol = 1e4*pref.techPrefs.chebfuneps;

% Example 1
f = sinh(ballfun(@(x,y,z)y));
exact = ballfun(@(x,y,z)sinh(y));
pass(1) = norm( f - exact ) < tol;

if (nargout > 0)
    pass = all(pass(:));
end
end


function writescores(pyra, model, info, fid)

% Write block scores to cascade score stats file.
%
% pyra     feature pyramid
% model    object model
% info     detection info from gdetect.m
% fid      file descriptor

% indexes into info from getdetections.cc
DET_USE = 1;    % current symbol is used
DET_IND = 2;    % rule index
DET_X   = 3;    % x coord (filter and deformation)
DET_Y   = 4;    % y coord (filter and deformation)
DET_L   = 5;    % level (filter)
DET_DS  = 6;    % # of 2x scalings relative to the start symbol location
DET_PX  = 7;    % x coord of "probe" (deformation)
DET_PY  = 8;    % y coord of "probe" (deformation)
DET_VAL = 9;    % score of current symbol
DET_SZ  = 10;   % <count number of constants above>

for i = 1:size(info,3)
  scores = zeros(model.numblocks, 1);

  for j = 1:model.numsymbols
    % skip unused symbols
    if info(DET_USE, j, i) == 0
      continue;
    end

    if model.symbols(j).type == 'T'
      scores = addfilterfeat(model, scores,           ...
                             info(DET_X, j, i),       ...
                             info(DET_Y, j, i),       ...
                             pyra.padx, pyra.pady,    ...
                             info(DET_DS, j, i),      ...
                             model.symbols(j).filter, ...
                             pyra.feat{info(DET_L, j, i)});
    else
      ruleind = info(DET_IND, j, i);
      if model.rules{j}(ruleind).type == 'D'
        bl = model.rules{j}(ruleind).def.blocklabel;
        dx = info(DET_PX, j, i) - info(DET_X, j, i);
        dy = info(DET_PY, j, i) - info(DET_Y, j, i);
        def = [-(dx^2); -dx; -(dy^2); -dy];
        scores(bl) = scores(bl) + model.rules{j}(ruleind).def.w*def;
      end
      bl = model.rules{j}(ruleind).offset.blocklabel;
      scores(bl) = scores(bl) + model.rules{j}(ruleind).offset.w;
    end
  end
  if abs(sum(scores) - info(DET_VAL, model.start, i)) > 1e-10
    fprintf('%f ~= %f\n', sum(scores), info(DET_VAL, model.start, i));
    error('wrong score');
  end
  dowrite(scores, fid);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% stores the filter feature vector in the example ex
function scores = addfilterfeat(model, scores, x, y, padx, pady, ds, fi, feat)
% model object model
% x, y  location of filter in feat (with virtual padding)
% padx  number of cols of padding
% pady  number of rows of padding
% ds    number of 2x scalings (0 => root level, 1 => first part level, ...)
% fi    filter index
% feat  padded feature map

fsz = model.filters(fi).size;
% remove virtual padding
fy = y - pady*(2^ds-1);
fx = x - padx*(2^ds-1);
f = feat(fy:fy+fsz(1)-1, fx:fx+fsz(2)-1, :);

bl = model.filters(fi).blocklabel;
scores(bl) = scores(bl) + model.filters(fi).w(:)' * f(:);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% write scores to fid
function dowrite(scores, fid)

% write total score and block scores
fwrite(fid, [sum(scores); scores], 'double');


function [w,cxe,w_pen,optimizerState,converged] = ...
    train_binary_classifier(classifier,classf,w0,objective_function,prior,...
                            penalizer,lambda,maxiters,maxCG,optimizerState,...
                            quiet,cstepHessian)
%
%   Supervised training of a regularized fusion.
%
%
% Inputs:
%
%   classifier: MV2DF function handle that maps parameters to llr-scores.
%               Note: The training data is already wrapped in this handle.
%
%   classf: 1-by-N row of class labels:
%                -1 for non_target,
%                +1 for target,
%                 0 for ignore
%
%   w0: initial parameters. This is NOT optional.
%
%   objective_function: A function handle to an Mv2DF function that
%                       maps the output (llr-scores) of classifier, to
%                       the to-be-minimized objective (called cxe).
%                       optional, use [] to invoke 'cllr_obj'.
%
%  prior: a prior probability for target to set the 'operating point'
%         of the objective function.
%         optional: use [] to invoke default of 0.5
%
%  penalizer: MV2DF function handle that maps parameters to a positive
%              regularization penalty.
%
%  lambda: a weighting for the penalizer
%
%  maxiters: the maximum number of Newton Trust Region optimization
%            iterations to perform. Note, the user can make maxiters
%            small, examine the solution and then continue training:
%            -- see w0 and optimizerState.
%
%
%
%  optimizerState: In this implementation, it is the trust region radius.
%                  optional:
%                    omit or use []
%                    If not supplied when resuming iteration,
%                    this may cost some extra iterations.
%                  Resume further iteration thus:
%   [w1,...,optimizerState] = train_binary_classifier(...);
%   ... examine solution w1  ...
%   [w2,...,optimizerState] = train_binary_classifier(...,w1,...,optimizerState);
%
%
%  quiet: if false, outputs more info during training
%
%
%  Outputs:
%    w: the solution.
%    cxe: normalized multiclass cross-entropy of the solution.
%         The range is 0 (good) to 1(useless).
%
%    optimizerState: see above, can be used to resume iteration.
%

if nargin==0
    test_this();
    return;
end

if ~exist('maxCG','var') || isempty(maxCG)
    maxCG = 100;
end

if ~exist('optimizerState','var')
    optimizerState=[];
end

if ~exist('prior','var') || isempty(prior)
    prior = 0.5;
end

if ~exist('objective_function','var') || isempty(objective_function)
    objective_function = @(w,T,weights,logit_prior) cllr_obj(w,T,weights,logit_prior);
end

%prior_entropy = -prior*log(prior)-(1-prior)*log(1-prior);
prior_entropy = objective_function([0;0],[1,-1],[prior,1-prior],logit(prior));

classf = classf(:)';

ntar = length(find(classf>0));
nnon = length(find(classf<0));
N = nnon+ntar;

weights = zeros(size(classf));
weights(classf>0) = prior/(ntar*prior_entropy);
weights(classf<0) = (1-prior)/(nnon*prior_entropy);
%weights remain 0, where classf==0

w=[];

if exist('penalizer','var') && ~isempty(penalizer)
    obj1 = objective_function(classifier,classf,weights,logit(prior));
    obj2 = penalizer(w);
    obj = sum_of_functions(w,[1,lambda],obj1,obj2);
else
    obj = objective_function(classifier,classf,weights,logit(prior));
end

w0 = w0(:);

if exist('cstepHessian','var') &&~ isempty(cstepHessian)
    obj = replace_hessian([],obj,cstepHessian);
end

[w,y,optimizerState,converged] = trustregion_newton_cg(obj,w0,maxiters,maxCG,optimizerState,[],1,quiet);

if exist('penalizer','var') && ~isempty(penalizer)
    w_pen = lambda*obj2(w);
else
    w_pen = 0;
end

cxe = y-w_pen;
if ~quiet
    fprintf('cxe = %g, pen = %g\n',cxe,w_pen);
end

function test_this()

%invoke test for linear_fuser, which calls train_binary_classifier
linear_fuser();


function xy = spike_position(dd, wPCA, wTEMP, yc, xc)

wTPC = gpuArray(wPCA' * wTEMP);

dT = gpuArray(dd);
for j = 1:size(dd,3)
    dT(:,:,j) = dT(:,:,j) * wTPC;
end

[nspikes, nPC, nchan] = size(dT);
[~, imax] = max(max(dT.^2, [], 3), [], 2);
dBest = gpuArray.zeros(nspikes, nchan, 'single');
for j = 1:nPC
    iX = imax==j;
    dBest(iX, :) = dT(iX, j, :);
end

dBest = max(0, dBest);
dBest = dBest ./ sum(dBest,2);

ysp = dBest * yc;
xsp = dBest * xc;

xy = [xsp, ysp];

xy = gather(xy);
end


function [grad, grad_W, grad_b, validFrameMask]= B_affine_transform(input_layers, curr_layer, future_layers, skip_grad)
if length(input_layers)==1
    input = input_layers{1}.a;
    W = curr_layer.W;
    b = curr_layer.b;
elseif length(input_layers)==2
    W = input_layers{1}.a;
    b = zeros(size(W,1),1);
    input = input_layers{2}.a;
end
validFrameMask = [];

if curr_layer.update==0
    grad_W = [];
    grad_b = [];
end

future_grad = GetFutureGrad(future_layers, curr_layer);

[n1,n2,n3] = size(future_grad);
if n3>1     % reshape the matrix to 2D
    [validFrameMask, variableLength] = getValidFrameMask(input_layers{length(input_layers)});
    if variableLength
        future_grad = PadShortTrajectory(future_grad, validFrameMask, 0);
%         input = PadShortTrajectory(input, validFrameMask, 0);
%         future_grad = future_grad(:,validFrameMask==0);
%         input = input(:,validFrameMask==0);
    end
    future_grad = reshape(future_grad, n1,n2*n3);
    input = reshape(input, size(input,1), n2*n3);
end

if curr_layer.update
    if issparse(input)
        visible_nonzero_idx = find(sum(abs(input),2)>0);
        visible_nonzero = full(input(visible_nonzero_idx,:));
        grad_W = sparse(size(W,1),size(W,2));
        grad_W(:,visible_nonzero_idx) = future_grad * visible_nonzero';
    else
        grad_W = conj(future_grad * input');
    end
    if isfield(curr_layer, 'mask')
        grad_W = grad_W .* curr_layer.mask;
    end
    if isfield(curr_layer, 'updateBias') && ~curr_layer.updateBias  % sometimes, we don't use bias
        grad_b = future_grad(:,1)*0;
    else
        grad_b = sum(future_grad,2);
    end
end
if isfield(curr_layer, 'skip_grad')
    skip_grad = skip_grad + curr_layer.skip_grad;
end
if skip_grad==0
    grad = W' * future_grad;
    if n3>1
        grad = reshape(grad, size(grad,1), n2, n3);
    end
else
    grad = [];
end

end


%Simple script to quickly demo use of CalCamArm.m

%path to images of checkerboards
imageFolder = './Example Data/Images/';
%loading arm transformations
load('./Example Data/armMat.mat');
%checkerboard square widths in mm
squareSize = 13.6;

%run calibration
[TBase, TEnd, cameraParams, TBaseStd, TEndStd, pixelErr] = CalCamArm(imageFolder, armMat, squareSize,'maxBaseOffset',0.5);

%print results
fprintf('\nFinal camera to arm base transform is\n')
disp(TBase);

fprintf('Final end effector to checkerboard transform is\n')
disp(TEnd);

fprintf('Final camera matrix is\n')
disp(cameraParams.IntrinsicMatrix');

fprintf('Final camera radial distortion parameters are\n')
disp(cameraParams.RadialDistortion);

fprintf('Final camera tangential distortion parameters are\n')
disp(cameraParams.TangentialDistortion);


classdef IWT2HD < dagnn.ElementWise

  properties (Transient)
      padding = 0
      wavename = 'haart'
      opts = {}
    numInputs
  end

  methods
    function outputs = forward(obj, inputs, params)
      obj.numInputs = numel(inputs) ;
      outputs{1} = vl_nniwt2(inputs{1}, [], ...
          'wavename', obj.wavename, 'padding', obj.padding, obj.opts{:}) ;
    end

    function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
      derInputs{1} =  vl_nniwt2(inputs{1},  derOutputs{1}, ...
          'wavename', obj.wavename, 'padding', obj.padding, obj.opts{:}) ;
      derParams = {0} ;
    end
    function outputSizes = getOutputSizes(obj, inputSizes)
      outputSizes = {} ;
    end

    function rfs = getReceptiveFields(obj)
        rfs = [] ;
    end

    function obj = IWT2HD(varargin)
      obj.load(varargin) ;
    end
  end
end


function varargout=mu_util(optn,varargin)
% MU_UTIL Various utility routines
%           This function should not be used directly; instead it is
%           is accessed by other high- and low-level functions.

% MU_UTIL is basically a driver for a number of lower-level routines collected
% together for convenience. They are specified by the first argument:
% 'clip'      - clipping routine
% 'axisticks' - generates a "nice" set of ticks, optimized for degrees/minutes on maps
%               angles of the circle.
% 'x/ygrid'   - generates the lines for axis grids
% 'xylimits'  - finds the x/y limits for a given map
% 'lllimits'  - finds the lat/long limits for a given map (usually for rectboxes)
% 'box'       - returns a line around the boundaries of the map.

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97
%
% This software is provided "as is" without warranty of any kind. But
% it's mine, so you can't sell it.

switch optn
  case 'clip'
    [varargout{1},varargout{2}]=m_clip(varargin{:});
  case 'axisticks'
    varargout{1}=m_getinterval(varargin{:});
  case {'xgrid','ygrid'}
    [varargout{1},varargout{2},varargout{3},varargout{4}]=m_rectgrid(optn,varargin{:});
  case 'xylimits'
    m_getxylimits;
  case 'lllimits'
    m_getlllimits;
  case 'box'
    [varargout{1},varargout{2}]=m_box(varargin{:});

end

%---------------------------------------------------------
function [Xc,Yc]=m_clip(cliptype,X,Xedge,indx,Y)
% M_CLIP performs clipping of data. Columns of points are
%        assumed to be lines; the first points outside the
%        clip area are recomputed to lie on the edge of the
%        region; others are converted to either NaN or
%        edge points depending on CLIPTYPE.
%
%        indx = 0 for points inside the clip region, 1
%               for those outside
%
%         'on'  - replaces points outside with NaN, but interpolates
%                 to provide points right on the border.
%         'patch' - replaces points outside with nearest border point
%         'point' - does no interpolation (just checks in/out)
%
% In general m_clip will be called 4 times, since it solves a 1-edge problem.

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97

Xc=X;
Yc=Y;

if ~strcmp(cliptype,'point')

  % Find regions where we suddenly come into the area
  % (indices go from 1 to 0)

  [i,j]=find(diff(indx)==-1);

  if any(i)
    I=i+(j-1)*size(X,1); % 1-d addressing

    % Linearly interpolate to boundary

    bt=(X(I+1)-X(I));
    ibt=abs(bt)<5*eps;
    if any(ibt), bt(ibt)=1*eps; end % In these cases the delta(Y) also = 0, so we just want
                                      % to avoid /0 warnings.
    Yc(I)=Y(I)+(Xedge-X(I)).*(Y(I+1)-Y(I))./bt;
    Yc(I(ibt))=(Y(I(ibt))+Y(I(ibt)+1))/2;
    Xc(I)=Xedge;
    indx(I(isfinite(Yc(I))))=0;
  end

  % Find regions where we suddenly come out of the area
  % (indices go from 0 to 1)

  [i,j]=find(diff(indx)==1);
  if any(i)

    I=i+(j-1)*size(X,1);

    bt=(X(I+1)-X(I));
    ibt=abs(bt)<5*eps;
    if any(ibt), bt(ibt)=eps;  end % In these cases the delta(Y) also = 0, so we just want
                                      % to avoid /0 warnings.

    Yc(I+1)=Y(I)+(Xedge-X(I)).*(Y(I+1)-Y(I))./bt;
    Yc(I(ibt)+1)=(Y(I(ibt))+Y(I(ibt)+1))/2;
    Xc(I+1)=Xedge;
    indx(I(isfinite(Yc(I+1)))+1)=0;
  end

end

switch cliptype
  case {'on','point'}
    Xc(indx)=NaN;
    Yc(indx)=NaN;
  case 'patch'
    Xc(indx)=Xedge;
end

%--------------------------------------------------------------------------
function gval=m_getinterval(gmin,gmax,gtick)
% M_GETINTERVAL picks nice spacing for grid ticks
%        This occurs when the following call is made:
%        TICKS=M_GRID('axisticks',MIN,MAX,APPROX_NUM_TICKS)
%

% Rich Pawlowicz (rich@ocgy.ubc.ca) 2/Apr/1997
%
% 9/Apr/98 - changed things so that max/min limits are not automatically
%            added (this feature made map corners messy sometimes)

% If ticks are specified, we just make sure they are within the limits
% of the map.

if length(gtick)>1
  gval=[gtick(gtick(:)>=gmin & gtick(:)<=gmax)];

% Otherwise, we try to fit approximately gtick ticks in the interval
else

  if gtick>2

    exactint=(gmax-gmin)/(gtick-1)*60; %interval in minutes

    % These are the intervals which we will allow (they are "nice" in the sense
    % that they come to various even multiples of minutes or degrees)
    niceints=[0.1 0.2 0.25 0.5 ...
              1 2 3 4 5 6 10 12 15 20 30 ...
              60*[1 2 3 4 5 6 8 9 10 12 15 18 20 25 30 40 50 60 100 120 180]];

    [dun,I]=min(abs(niceints-exactint));

    gval=niceints(I)/60*[ceil(gmin*60/niceints(I)):fix(gmax*60/niceints(I))];

    gval=[gval(gval>=gmin & gval<=gmax) ];
  else
    gval=[gmin gmax];
  end
end

%--------------------------------------------------------------
function [X,Y,vals,labI]=m_rectgrid(direc,Xlims,Ylims,Nx,Ny,label_pos)
% M_RECTGRID This handles some of the computations involved in creating grids
%            for rectangular maps. Essentially we make our "first guess" using the
%            lat/long limits. Then these curves are clipped to the boundaries, after
%            which we use the clip points as "new" boundaries and recompute the lines.

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97

global MAP_PROJECTION MAP_VAR_LIST

Ny1=Ny-1;
Ny2=Ny*2;
Ny21=Ny2-1;

% First try some wildly oversampled lines (not including the boundaries)

vals=mu_util('axisticks',Xlims(1),Xlims(2),Nx);

if strcmp(MAP_VAR_LIST.rectbox,'on') |  strcmp(MAP_VAR_LIST.rectbox,'circle')

 % We don't want the end limits here.
 if vals(end) == Xlims(2), vals(end) = []; end
 if vals(1)   == Xlims(1), vals(1)   = []; end

 if direc(1)=='x'
  [lg,lt]=meshgrid(vals,Ylims(1)+diff(Ylims)*[0:1/Ny1:1]);
 else
  [lt,lg]=meshgrid(vals,Ylims(1)+diff(Ylims)*[0:1/Ny1:1]);
 end

 % But sneakily we clip them in transforming, so we end up with isfinite values only
 % inside the axis limits

 [X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',lg,lt,'clip','on');

 % Now we find the first/last unclipped values; these will be our correct starting points.
 % (Note I am converting to one-dimensional addressing).

 istart=sum(cumsum(isfinite(X))==0)+1+[0:size(X,2)-1]*size(X,1);
 iend=size(X,1)-sum(cumsum(isfinite(flipud(X)))==0)+[0:size(X,2)-1]*size(X,1);

 % Now go back and find the lat/longs corresponding to those points; these are our new
 % starting points for the lines (Note that the linear interpolation for clipping at boundaries
 % means that they will not *quite* be the exact longitudes due to curvature, but they should
 % be very close.

 if direc(1)=='x'

  [lgs,lts]=feval(MAP_PROJECTION.routine,'xy2ll',X(istart),Y(istart),'clip','off');
  [lgs,lte]=feval(MAP_PROJECTION.routine,'xy2ll',X(iend),Y(iend),'clip','off');

  % Finally compute the lines within those limits (these *may* include some out-of-bounds points
  % depending on the geometry of the situation; these are converted to NaN as usual.

  [X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',vals(ones(Ny2,1),:),...
              lts(ones(Ny2,1),:)+[0:1/Ny21:1]'*(lte-lts),'clip','on');

 else

  [lgs,lts]=feval(MAP_PROJECTION.routine,'xy2ll',X(istart),Y(istart),'clip','off');
  [lge,lts]=feval(MAP_PROJECTION.routine,'xy2ll',X(iend),Y(iend),'clip','off');

  % Longitudes should be increasing here, but we can run into wrap problems after
  % the tansformations back and forth. It is for this line that I need to make
  % long-lims just a tad less than 360 when really they should be 360 (in m_lllimits)

  lge(lge<=lgs)=lge(lge<=lgs)+360;

  [X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',lgs(ones(Ny2,1),:)+[0:1/Ny21:1]'*(lge-lgs),...
              vals(ones(Ny2,1),:),'clip','on');

 end

else
 if direc(1)=='x'
  [lg,lt]=meshgrid(vals,Ylims(1)+diff(Ylims)*[0:1/Ny1:1]);
 else
  [lt,lg]=meshgrid(vals,Ylims(1)+diff(Ylims)*[0:1/Ny1:1]);
 end
 [X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',lg,lt,'clip','off');

end

switch label_pos
  case {'left','bottom','west','south'}
    labI=1;
  case 'middle'
    labI=round(size(X,1)/2+1/2);
  case {'right','top','east','north'}
    labI=size(X,1);
end

%--------------------------------------------------------------------------------
function m_getxylimits
% M_GET_LIMITS Converts X/Y limits to lat/long limits
%              This is a chunk of code that is needed for most projections.

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97

global MAP_PROJECTION MAP_VAR_LIST

% Start with the user-specified lat/longs.

MAP_VAR_LIST.lats=MAP_VAR_LIST.ulats;
MAP_VAR_LIST.longs=MAP_VAR_LIST.ulongs;

% Now, let's get the map x/ylims
bX=MAP_VAR_LIST.longs(1)+diff(MAP_VAR_LIST.longs)*[0:1/30:1];
bY=MAP_VAR_LIST.lats(1)+diff(MAP_VAR_LIST.lats)*[0:1/30:1];
bX=[bX MAP_VAR_LIST.longs(2*ones(1,31)) fliplr(bX) MAP_VAR_LIST.longs(ones(1,31)) ];
bY=[MAP_VAR_LIST.lats(ones(1,31)) bY MAP_VAR_LIST.lats(2*ones(1,31)) fliplr(bY) ];
[X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',bX,bY,'clip','off');
MAP_VAR_LIST.xlims=[min(X) max(X)];
MAP_VAR_LIST.ylims=[min(Y) max(Y)];

%-------------------------------------------------------------------------------
function m_getlllimits
% M_GET_LIMITS Converts X/Y limits to lat/long limits
%              This is a chunk of code that is needed for most projections.

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97

global MAP_PROJECTION MAP_VAR_LIST

[bX,bY]=mu_util('box',31);
% Get its lat/longs.

[lg,lt]=feval(MAP_PROJECTION.routine,'xy2ll',bX,bY,'clip','off');
% Take real part because otherwise funny things might happen if the box is very large

MAP_VAR_LIST.lats=[min(real(lt)) max(real(lt))];

% Are the poles within the axis limits? (Test necessary for oblique mercator and azimuthal)
[px,py]=feval(MAP_PROJECTION.routine,'ll2xy',[0 0],[-90 90],'clip','point');
if isfinite(px(1)), MAP_VAR_LIST.lats(1)=-90; end
if isfinite(px(2)), MAP_VAR_LIST.lats(2)= 90; end

if any(isfinite(px))
  MAP_VAR_LIST.longs=[-179.9 180]+exp(1); % we add a weird number (exp(1)) to get away from
                         % anything that might conceivably be desired as a
                         % boundary - it makes grid generation easier.
                         % Also make the limits just a little less than 180, this
                         % is necessary because I have to have the first and last points
                         % of lines just a little different in order to figure out orientation
                         % in 'm_rectgrid'
else
  MAP_VAR_LIST.longs=[min(lg) max(lg)];
  if all(isnan(px)) & diff(MAP_VAR_LIST.longs)>360*30/31
    ii=lg<mean(MAP_VAR_LIST.longs);
    lg(ii)=lg(ii)+360;
    MAP_VAR_LIST.longs=[min(lg) max(lg)];
  end
end

%------------------------------------------------------------------------
function [X,Y]=m_box(npts)
% M_BOX  Computes coordinates of the map border.
%

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/April/97

global MAP_PROJECTION MAP_VAR_LIST

n1=npts-1;

switch MAP_VAR_LIST.rectbox
  case 'on'
    X=MAP_VAR_LIST.xlims(1)+diff(MAP_VAR_LIST.xlims)*[0:1/n1:1];
    Y=MAP_VAR_LIST.ylims(1)+diff(MAP_VAR_LIST.ylims)*[0:1/n1:1];
    X=[X MAP_VAR_LIST.xlims(2*ones(1,npts)) fliplr(X) MAP_VAR_LIST.xlims(ones(1,npts))];
    Y=[MAP_VAR_LIST.ylims(ones(1,npts)) Y  MAP_VAR_LIST.ylims(2*ones(1,npts)) fliplr(Y)];
  case 'off'
    lg=MAP_VAR_LIST.longs(1)+diff(MAP_VAR_LIST.longs)*[0:1/n1:1];
    lg=[lg MAP_VAR_LIST.longs(2*ones(1,npts)) fliplr(lg) MAP_VAR_LIST.longs(ones(1,npts))]';
    lt=MAP_VAR_LIST.lats(1)+diff(MAP_VAR_LIST.lats)*[0:1/n1:1];
    lt=[MAP_VAR_LIST.lats(ones(1,npts)) lt  MAP_VAR_LIST.lats(2*ones(1,npts)) fliplr(lt)]';
    [X,Y]=feval(MAP_PROJECTION.routine,'ll2xy',lg,lt,'clip','off');
  case 'circle'
    n1=npts*3-1;
    X=MAP_VAR_LIST.rhomax*cos([0:n1]/n1*pi*2);
    Y=MAP_VAR_LIST.rhomax*sin([0:n1]/n1*pi*2);
end


% poolType = 'mean' or 'max'
% poolLayer = integer layer number after which we do the pooling
function layer = genNetworkFeedForward_pool(inputDim, hiddenLayerSize, outputDim, costFn, poolType, poolAfterNlayer, LastActivation4MSE)
if nargin<7
    LastActivation4MSE = 'linear';
end

layer = genNetworkFeedForward_v2(inputDim, hiddenLayerSize, outputDim, costFn, LastActivation4MSE);

poolLayer.name = poolType;
poolLayer.dim = [1 1]*layer{poolAfterNlayer}.dim(1);
poolLayer.prev = layer{poolAfterNlayer}.prev;
layer = [layer(1:poolAfterNlayer) poolLayer layer(poolAfterNlayer+1:end)];

% automatically derive the list of layers that the output of the current layer goes.
for i=1:length(layer); layer{i}.next = []; end
for i=length(layer):-1:1
    if isfield(layer{i}, 'prev')
        for j=1:length(layer{i}.prev)
            layer{i+layer{i}.prev(j)}.next(end+1) = -layer{i}.prev(j);
        end
    end
end

end


%SAD	Stereo matching using Zero Mean Sum of Absolute Differences metric
%
%	[DISP SCORES] = ZSAD(LEFT, RIGHT, LEFT_RIGHT, WIN_SIZE, DISP_RANGE)
%
%       DISP = Disparity map
%       SCORES = ZSAD scores at each disparity
%       LEFT, RIGHT = images
%       LEFT_RIGHT = 'l' if wrt left image, 'r' if wrt right image
%       WIN_SIZE = window size or [x_size y_size]
%       DISP_RANGE = [START_DISPARITY END_DISPARITY]
% Author: Jasmine E. Banks (jbanks@ieee.org)

% Copyright in this software is owned by CSIRO.  CSIRO grants permission to
% any individual or institution to use, copy, modify, and distribute this
% software, provided that:
%
% (a)     this copyright and permission notice appears in its entirety in or
% on (as the case may be) all copies of the software and supporting
% documentation;
%
% (b)     the authors of papers that describe software systems using this
% software package acknowledge such use by citing the paper as follows:
%
%     "Quantitative Evaluation of Matching Methods and Validity Measures for
%     Stereo Vision" by J. Banks and P. Corke, Int. J. Robotics Research,
%     Vol 20(7), 2001; and
%
% (c)     users of this software acknowledge and agree that:
%
%   (i) CSIRO makes no representations about the suitability of this software
%   for any purpose;
%
%   (ii) that the software is provided "as is" without express or implied
%   warranty; and
%
%   (iii) users of this software use the software entirely at their own risk.


function [ a, seed ] = runs_simulate ( m, n, seed )

%*****************************************************************************80
%
%% RUNS_SIMULATE simulates a case governed by the Runs PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the parameters of the PDF.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, integer A(M+N), a sequence of M 0's and N 1's chosen
%    uniformly at random.
%
%    Output, integer SEED, a seed for the random number generator.
%
  a(1:m) = 0;
  a(m+1:m+n) = 1;

  for i = 1 : m+n-1

    [ j, seed ] = i4_uniform ( i, m+n, seed );

    k    = a(i);
    a(i) = a(j);
    a(j) = k;

  end

  return
end


function [pvec, pstruct] = tapas_ehgf_jget_transp(r, ptrans)
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2013-2020 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

pvec    = NaN(1,length(ptrans));
pstruct = struct;

l = r.c_prc.n_levels;

pvec(1:l)         = ptrans(1:l);                                  % mux_0
pstruct.mux_0     = pvec(1:l);
pvec(l+1:2*l)     = exp(ptrans(l+1:2*l));                         % sax_0
pstruct.sax_0     = pvec(l+1:2*l);
pvec(2*l+1:3*l)   = ptrans(2*l+1:3*l);                            % mua_0
pstruct.mua_0     = pvec(2*l+1:3*l);
pvec(3*l+1:4*l)   = exp(ptrans(3*l+1:4*l));                       % saa_0
pstruct.saa_0     = pvec(3*l+1:4*l);
pvec(4*l+1)       = exp(ptrans(4*l+1));                           % kau
pstruct.kau       = pvec(4*l+1);
pvec(4*l+2:5*l)   = exp(ptrans(4*l+2:5*l));                       % kax
pstruct.kax       = pvec(4*l+2:5*l);
pvec(5*l+1:6*l-1) = exp(ptrans(5*l+1:6*l-1));                     % kaa
pstruct.kaa       = pvec(5*l+1:6*l-1);
pvec(6*l)         = ptrans(6*l);                                  % omu
pstruct.omu       = pvec(6*l);
pvec(6*l+1:7*l)   = ptrans(6*l+1:7*l);                            % omx
pstruct.omx       = pvec(6*l+1:7*l);
pvec(7*l+1:8*l)   = ptrans(7*l+1:8*l);                            % oma
pstruct.oma       = pvec(7*l+1:8*l);

end


function make_train_lut

    hks_i = comm.KasamiSequence('SamplesPerFrame', 65,'Index',1);
    hks_q = comm.KasamiSequence('SamplesPerFrame', 65,'Index',3);
    x_i = step(hks_i);
    x_q = step(hks_q);
    t_i = x_i*2-1;
    t_q = x_q*2-1;

    fid = fopen('TB_i.m','w+');
    fprintf(fid,'function y = TB_i\n');
    fprintf(fid,'%%#codegen\n');
    fprintf(fid,'y = [\n');
    fprintf(fid,'%1d\n',t_i);
    fprintf(fid,'];\n');
    fclose(fid);
    fid = fopen('TB_q.m','w+');
    fprintf(fid,'function y = TB_q\n');
    fprintf(fid,'%%#codegen\n');
    fprintf(fid,'y = [\n');
    fprintf(fid,'%1d\n',t_q);
    fprintf(fid,'];\n');
    fclose(fid);
end


function ll = hsvargplvmLogLikelihood(model)

F_leaves = hsvargplvmLogLikelihoodLeaves(model.layer{1});
F_nodes = hsvargplvmLogLikelihoodNode(model);
F_entropies = hsvargplvmLogLikelihoodEntropies(model);
% This refers to the KL quantity of the top node. The likelihood part is
% computed in hsvargplvmLogLikelihoodNode.
F_parent = hsvargplvmLogLikelihoodParent(model.layer{model.H});

ll = F_leaves + F_nodes + F_entropies + F_parent;

%--- NEW!!! TEST!
% %{
for h=1:model.H
    % If there's a prior on some parameter, add the (minus) corresponding
    % likelihood.
    for m=1:model.layer{h}.M
        ll = ll + vargplvmParamPriorLogProb(model.layer{h}.comp{m});
    end
end
% %}
%---

end

% The ln p(Y|X) terms
function F_leaves = hsvargplvmLogLikelihoodLeaves(modelLeaves)

F_leaves = 0;
for m=1:modelLeaves.M
    modelLeaves.comp{m}.onlyLikelihood = true;
    F_leaves = F_leaves + vargplvmLogLikelihood(modelLeaves.comp{m});
end
end

% The <ln p(X_h | X_{h-1})>_{q(X_{h-1}} nodes
function F_nodes = hsvargplvmLogLikelihoodNode(model)
F_nodes = 0;
for h=2:model.H
    % It's just like the leaves computation, the only difference is the
    % trace(Y*Y') term which now is replaced by an expectation w.r.t the
    % latent space of the previous layer. However, this replacement is done
    % in hsvargplvmUpdateStats and we dont have to worry here about it
    F_nodes = F_nodes + hsvargplvmLogLikelihoodLeaves(model.layer{h});
end

end

% The H_{q(X_h)} nodes, h ~= H
function F_entropies = hsvargplvmLogLikelihoodEntropies(model)
F_entropies = 0;
for h=1:model.H-1
    vardist = model.layer{h}.vardist;
    F_entropies = F_entropies + 0.5*(vardist.numData*vardist.latentDimension* ...
            (log(2*pi) + 1) + sum(sum(log(vardist.covars))));
end
if isfield(model, 'DEBUG_entropy') && model.DEBUG_entropy
    F_entropies = - F_entropies;
end

end

% The -KL[q(X_H) || p(X_H)]
function F_parent = hsvargplvmLogLikelihoodParent(modelParent)
%if modelParent.M > 1
%    warning('Not implemented multiple models in parent node yet')
%end
% Copied from vargplvmLogLikelihood:
if isfield(modelParent, 'dynamics') & ~isempty(modelParent.dynamics)
        % A dynamics model is being used.
        F_parent = modelVarPriorBound(modelParent);
        F_parent = F_parent + 0.5*modelParent.q*modelParent.N; %%% The constant term!!
else
    varmeans = sum(sum(modelParent.vardist.means.*modelParent.vardist.means));
    varcovs = sum(sum(modelParent.vardist.covars - log(modelParent.vardist.covars)));
    F_parent = -0.5*(varmeans + varcovs) + 0.5*modelParent.q*modelParent.N;
end
end


function [stats,st] = SStat_CoxExt(sID_ext,X_ext,d_ext,t_ext,e)
% [stats,st] = SStat_CoxExt(sID_ext,X_ext,d_ext,t_ext,e)
%
% Parameter estimation for the extended Cox model. This function uses as
% input the output of SStat_X_ext but with X_ext having new time-dependent
% columns added by the user (eg. the product of a column of X_ext with
% t_ext. Survival time ties are handled using Efron's method.
%
% Input
% sID_ext: Extended subjects' IDs (nx1).
% X_ext: Extended design matrix (nxp).
% d_ext: Extended censorship status vector (nx1).
% t_ext: Extended survival time vector (nx1).
% e: Convergence epsilon (gradient's norm). Default 10^-3;
%
% Output
% stats.Bhat: Estimated vector of the population regression parameters.
% stats.CovBhat: Estimated covariance matrix of the population regression
% parameters.
% stats.llh: Values of the maximum log-likelihood across the optimization
% process.
% st: Termination state (1 for convergence and 0 otherwise).
%
% $Revision: 1.1 $  $Date: 2015/01/06 17:04:02 $
% Original Author: Jorge Luis Bernal Rusiel
% CVS Revision Info:
%    $Author: mreuter $
%    $Date: 2015/01/06 17:04:02 $
%    $Revision: 1.1 $
% References: Kleinbaum, D.G., Klein, M., 2005. Survival analysis. A self-
% learning approach, second edition. New York: Springer..
%
if nargin < 4
    error('Too few inputs');
elseif nargin < 5
    e = 0.001;
end;
tic;
[n,p] = size(X_ext);
if (length(sID_ext)~=n) || (length(d_ext)~=n) || (length(t_ext)~=n)
    error(['The design matrix X_ext, censorship status vector d_ext, time'...
        ' vector t_ext and subject ID vector sID_ext must all have the same'...
        ' number of rows.']);
end;
%indices of unique failure times in ft_ix (last index when ties happen)
st_ix = find(d_ext==1);
[~,ft_ix] = unique(t_ext(st_ix),'last');
ft_ix = st_ix(ft_ix);
%Starting values
Bhat = zeros(p,1);

%% Iterations
nit = 50;
gnorm = e+1;
it = 1;
display('Starting Newton-Raphson iterations');
while (gnorm>e) && (it<=nit)
    gr = SStat_Gradient(X_ext,t_ext,Bhat,ft_ix);
    He = SStat_Hessian(X_ext,t_ext,Bhat,ft_ix);
    if (cond(He) < 1e+10)
        invHe = He\eye(p);
    else
        [Vtemp,Dtemp] = eig(He);
        invHe = Vtemp*diag(1./max(diag(Dtemp),1e-5))*Vtemp';
    end
    Bhat = Bhat - invHe*gr;
    %log-likelihood
    llh = SStat_Likelihood(X_ext,t_ext,Bhat,ft_ix);
    display(['Likelihood at iteration ' num2str(it) ' : ' num2str(llh)]);
    gnorm = norm(gr);
    display(['Gradient norm: ' num2str(gnorm)]);
    it = it+1;
end;
%% Termination
z_sc = Bhat./sqrt(diag(-invHe));
pval = 2*(1-normcdf(abs(z_sc),0,1));
stats = struct('Bhat',Bhat,'zscore',z_sc,'pval',pval,'CovBhat',-invHe,'llh',llh);
if (gnorm<=e)
    st = 1;
else
    st = 0;
    display(['Algorithm does not converge after ' num2str(nit)...
        ' iterations!!!']);
end;
et = toc;
display(['Total elapsed time is ' num2str(et) ' seconds']);
end

%% Likelihood, Gradient and Hessian

function llk = SStat_Likelihood(X_ext,t_ext,Bhat,ft_ix)
%
% Log-likelihood value.
%
% Input
% X_ext: Extended design matrix.
% t_ext: Extended survival time vector.
% Bhat: Estimated vector of the population regression parameters.
% ft_ix: Failure time indices in X_ext (last index if any tie).
%
% Output
% llk: Log-likelihood value.
%
llk = 0;
nft = length(ft_ix);
for j=1:nft
    term = 0;
    ties = ft_ix(t_ext(ft_ix(j))==t_ext(ft_ix));
    nties = length(ties)-1;
    lpr = X_ext(ties,:)*Bhat;
    aux1 = sum(exp(lpr));
    aux2 = sum(exp(X_ext(t_ext(ft_ix(j))==t_ext,:)*Bhat));
    for l=0:nties
        term = term + log(aux2-l*aux1/(nties+1));
    end;
    llk = llk + sum(lpr) - term;
end;
end

function gr = SStat_Gradient(X_ext,t_ext,Bhat,ft_ix)
%
% Gradient vector for the log-likelihood.
%
% Input
% X_ext: Extended design matrix.
% t_ext: Extended survival time vector.
% Bhat: Estimated vector of the population regression parameters.
% ft_ix: Failure time indices in X_ext (last index if any tie).
%
% Output
% gr: Gradient vector.
%
p = size(X_ext,2);
gr = zeros(p,1);
nft = length(ft_ix);
for j=1:nft
    ties = ft_ix(t_ext(ft_ix(j))==t_ext(ft_ix));
    nties = length(ties)-1;
    riskset = t_ext(ft_ix(j))==t_ext;
    term1 = sum(X_ext(ties,:),1);
    term2 = exp(X_ext(riskset,:)*Bhat);
    term3 = exp(X_ext(ties,:)*Bhat);
    term4 = term2'*X_ext(riskset,:);
    term5 = term3'*X_ext(ties,:);
    term = 0;
    for l=0:nties
        term = term + (term4-l*term5/(nties+1))/(sum(term2)-l*sum(term3)/(nties+1));
    end;
    gr = gr + (term1 - term)';
end;
end

function He = SStat_Hessian(X_ext,t_ext,Bhat,ft_ix)
%
% Hessian matrix for the log-likelihood.
%
% Input
% X_ext: Extended design matrix.
% t_ext: Extended survival time vector.
% Bhat: Estimated vector of the population regression parameters.
% ft_ix: Failure time indices in X_ext (last index if any tie).
%
% Output
% He: Hessian matrix.
%
p = size(X_ext,2);
He = zeros(p,p);
nft = length(ft_ix);
for j=1:nft
    ties = ft_ix(t_ext(ft_ix(j))==t_ext(ft_ix));
    nties = length(ties)-1;
    rsk_ix = find(t_ext(ft_ix(j))==t_ext);
    m = length(rsk_ix);
    term1 = 0;
    for i=1:m
        term1 = term1 + exp(X_ext(rsk_ix(i),:)*Bhat)*X_ext(rsk_ix(i),:)'*X_ext(rsk_ix(i),:);
    end;
    term2 = 0;
    for i=1:nties
        term2 = term2 + exp(X_ext(ties(i),:)*Bhat)*X_ext(ties(i),:)'*X_ext(ties(i),:);
    end;
    term3 = sum(exp(X_ext(rsk_ix,:)*Bhat));
    term4 = sum(exp(X_ext(ties,:)*Bhat));
    term5 = exp(X_ext(rsk_ix,:)*Bhat)'*X_ext(rsk_ix,:);
    term6 = exp(X_ext(ties,:)*Bhat)'*X_ext(ties,:);
    term = 0;
    for l=0:nties
        Z = term5 - l*term6/(nties+1);
        phi = term3 - l*term4/(nties+1);
        term = term + (term1-l*term2/(nties+1))/phi - Z'*Z/(phi*phi);
    end;
    He = He - term;
end;
end


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
% function [ML,minLevel,maxLevel,fig] = getMultilevel(IS,omega,m,varargin)
%
% compute a multi-level representation of an image IS or a list of images
% IS = {T,R,MT,MR,...}
%
%  Input:
%      IS        an image or a list of images
%      omega     domain specification
%      m         number of discretization points
%      varargin  optional parameter, see below
%
% Output:
%   ML       struct containing multi-level representation
%                   ML{j} =  {T_j,R_j,omega,m_j}
%   minLevel     coarsest level
%   maxLevel     finest   level
%   fig          handle to the graphical output
%
% A continuous representation of an image serves as a starting point. Using a cell
% centered grid, the data is replace by interpolated values. The representation on
% a coarser level is obtained by averaging over adjacent cells (see the filters for
% options).
%
% ML{level} is a structure containing the image(s), omega, and m,
% where level runs 0:maxLevel, ML{level} = [] for level < minLevel.
% Note that we assume m=2^p, p integer; the original data size is arbitrary.
%==============================================================================

function [ML,minLevel,maxLevel,fig] = getMultilevel(IS,omega,m,varargin)

if nargin == 0,    % show help and provide minimal example
  help(mfilename);
  runMinimalExample;
  ML = 'endOfMinimalExample';
  return;
end;

if nargin == 1,
  % simply return ML, minLevel, maxLevel
  ML = IS; maxLevel = length(ML); fig = 0;
  for minLevel=maxLevel:-1:1,
    if minLevel == 1 || isempty(ML{minLevel-1}), break; end;
  end;
  return;
end;

% start the work
fig      = 2;                  % figure number for output
dopause  = 0;                  % make pause for demonstrations
filter   = 'block';            % discrete smoothing kernel
minLevel = 3;                  % minimal level size
names    = {'T','R','Q','Q1','Q2','Q3','Q4','Q5'};
restrictdim = ones(size(m));   % by default: restrict all dimensions
imgModel = @linearInter;       % use linear interpolation as a default
                               % image model

for k=1:2:length(varargin),    % overwrite defaults
  eval([varargin{k},'=varargin{',int2str(k+1),'};']);
end;

if ~iscell(IS), IS = {IS}; end;% in case of a single image input
lenIS = length(IS);                 % number of images to be handled
dim   = length(omega)/2;            % spacial dimension
maxLevel = ceil(log2(min(m(restrictdim==1))));      % finest level

% messaging
msg = sprintf('%s(%d image(s), filter=%s, %dD data,level=%d:%d)',...
  mfilename,lenIS,filter,dim,minLevel,maxLevel);

fprintf('%s, figure=%d\n',msg,fig);
fprintf('note: model from data of any dimension is sampled on a grid of size m\n');
fprintf('      at present it is assume that m = 2.^p, p an interger\n');
fprintf('      ML is an array of cells, where the i-th entry contains the data\n');
fprintf('      of size 2^p, with some modifications is not all dimensions are equal\n');

% some output to the console
fprintf('%s: [',mfilename);

omegak = @(k)omega(min(1+(k>1),size(omega,1)),:);

% start the loop from maxlevel to minlevel
for level = maxLevel:-1:minLevel
  if level == maxLevel,
    % replace data by the interpolant on x
    for k=1:lenIS,
      sizeData = size(IS{k});
      % note: data is either m1-by-....-by-md
      %                   or m1-by-....-by-md-by-nrVolume
      % but the 1d case is tricky

      if (dim>1) && (length(sizeData) > dim),
        nrVolume = sizeData(end),
        sizeData(end) = [];
        keyboard
      else
        nrVolume = 1;
      end;

      data  = reshape(IS{k},prod(sizeData),nrVolume);
      block = zeros(prod(m),nrVolume);
      xc    = getCellCenteredGrid(omegak(k),m);
      % create dsample of size m from image model (interpolation) obtained from data
      for vol=1:size(data,2),
        block(:,vol) = imgModel(reshape(data(:,vol),sizeData),omegak(k),xc);
      end

      IS{k} = reshape(block,[m,nrVolume]);
    end;
    fprintf('%d',level);
  else
    % restrict the image to the coarser grid
    L = ML{level+1};
    for k=1:lenIS, % run over all images
      for j=1:dim, % run over all dimensions
        if restrictdim(j),
            IS{k} = restrict(IS{k},dim,j,filter);
        end
      end;
    end;
    fprintf(',%d',level);
  end;

  % store the current level data in a struct
  L.m = size(IS{1}); L.m = L.m(1:dim); L.omega = omega;
  for k= 1:lenIS,
    L = setfield(L,names{k},IS{k});
  end;
  ML{level} = L;

  if fig, % do some plots
    if level == maxLevel,
       FAIRfigure(fig,'figname',msg,'position','default');
    end;

    str = @(k) sprintf('%s(level=%d), %s',...
      names{k},level,sprintf('m=[%s]',sprintf(' %d',L.m)));
    p0 = level-minLevel+1;
    dp = (maxLevel-minLevel+1);
    figureh(fig);
    for k=1:lenIS,
      xc = getCellCenteredGrid(omegak(k),L.m);
      subplot(lenIS,dp,p0+(k-1)*dp);
      viewImage(imgModel(IS{k},omegak(k),xc),omegak(k),L.m);
      title(str(k));
    end;
    if dopause, pause; else drawnow; end;
  end;
end;
fprintf('] done\n');

%------------------------------------------------------------------------------
function T = restrict(T,dim,j,filter)
J = [j,setdiff(1:dim,j)]; J = [J dim+1]; % bring dimension j to front
T = permute(T,J);
if rem(size(T,1),2), T(end+1,:,:,:) = T(end,:,:,:); end;
switch filter,
  case 'gaussian',
    Ta = zeros(size(T)+[2,zeros(1,ndims(T)-1)]);
    Ta(2:end-1,:,:,:) = T; Ta([1,end],:,:,:) = Ta([2,end-1],:,:,:);
    T =   0.125 * Ta(1:end-3,:,:,:) + 0.375 * Ta(2:end-2,:,:,:) ...
        + 0.375 * Ta(3:end-1,:,:,:) + 0.125 * Ta(4:end,:,:,:);
    T = T(1:2:end,:,:,:);
  case 'block'
    T = (T(1:2:end,:,:,:)+T(2:2:end,:,:,:))/2;
  case 'harmonic'
    T = 1./(T+eps);
    T = (T(1:2:end,:,:,:)+T(2:2:end,:,:,:))/2;
    T = 1./T;
end;
T = ipermute(T,J); % bring j back home

%------------------------------------------------------------------------------

function runMinimalExample
Tdata = double(flipud(imread('hands-T.jpg'))');
Rdata = double(flipud(imread('hands-R.jpg'))');
omega = [0,20,0,25]; % specify physical domain
m     = size(Tdata);

% set view options and interpolation options and initialize viewer and interpolator
viewPara = {'viewImage','viewImage2D','colormap','gray(256)'};
viewImage('reset',viewPara{:});
% create multilevel representation of the data
ML = getMultilevel({Tdata,Rdata},omega,m,'fig',2);

%==============================================================================


function [ T, trnorm, U ] = tensor_shrinkage( X, tau, mode )
% X and T are tensors
global tmode;
tmode = mode;

Xmat = tenmat(X,mode);
[Tmat, trnorm, U] = matrix_shrinkage( double(Xmat), tau );
% [ U, S, V ] = svd( double(Xmat), 'econ' );
% s = diag(S);
% s = s - tau;
% s( s < 0 ) = 0;
% Tmat = scale_matrix( U, s, 1 ) * V';
T = tensor( tenmat( Tmat, Xmat.rdims, Xmat.cdims, Xmat.tsize ) );

end


cwpos = 1*ones(length(wordsbi), 1);
cwneg = 1*ones(length(wordsbi), 1);

nbind = train_ind;
nbsent = allSNumBi(nbind);
nblbl = labels(nbind);
ppos = sum(nblbl)/length(nblbl); pneg = 1 - ppos;

for i = 1:length(nbsent)
    nbsentraw = nbsent{i};
    nbsentraw=nbsentraw(nbsentraw>0);
    updates = unique(nbsentraw);
    counts = power(histc(nbsentraw, updates)', trainp);
     % counts = ones(size(histc(nbsentraw, updates)));
    if nblbl(i) == 1
        cwpos(updates) = cwpos(updates) + counts * (0.5/ppos);
    else
        cwneg(updates) = cwneg(updates) + counts * (0.5/pneg);
    end
end
% cwpos = cwpos * sum(cwneg) ./ sum(cwpos);
pwpos = log(cwpos / sum(cwpos));
pwneg = log(cwneg / sum(cwneg));

% cwpos = cwpos ./ norm(cwpos);
% cwneg = cwneg ./ norm(cwneg);

nbindtst = test_ind;
nbsenttst = allSNumBi(nbindtst);
nblbltst = labels(nbindtst);

pred = zeros(1, length(nbsenttst));
% predvote = zeros(1, length(nbsenttst));
% load('../data/sentiLex.mat', 'sentlex', 'sentlexval');
%
% sentimap = containers.Map(sentlex, sentlexval);
% wordSent = zeros(length(words),1);
% for i = 1:length(words)
%         if sentimap.isKey(words{i}) && sentimap(words{i}) <= 1
%            wordSent(i) = 2*sentimap(words{i}) - 1;
%         end
% end

softpred = zeros(size(pred));
bipred = zeros(1, length(nbsenttst));
unipred = zeros(1, length(nbsenttst));
for i = 1:length(nbsenttst)
    nbsentraw = nbsenttst{i};
    nbsentraw=nbsentraw(nbsentraw>0);

    updates = unique(nbsentraw);
    counts = power(histc(nbsentraw, updates), testp)';

    sentend = floor(length(nbsentraw)/2);
    sentword = nbsentraw(1:sentend);
    sentbi = nbsentraw(sentend+1:end);

    predsent = cwpos([sentword]) ./ cwneg([sentword]);
    totsent = cwpos([sentword]) + cwneg([sentword]);
    predbi = cwpos([sentbi]) ./ cwneg([sentbi]);

    weightsent = 1 - flukeprob(cwpos([sentword]),  cwneg([sentword]));
    weightbi = 1 - flukeprob(cwpos([sentbi]),  cwneg([sentbi]));

    predval = sum(log(predsent) ) + ...
        sum(log(predbi)) + log(ppos) - log(pneg) ;

    bipred(i) =  prod(predbi) > 1;
    unipred(i) =  prod(predsent) > 1;
    pred(i) = predval > 0;

%     softpredp(i) = poslog;
%     softpredn(i) = neglog;
    vis = 0;

    if vis && pred(i) ~= nblbltst(i)
        if nblbltst(i) ==0
            i;
        end
    for s = 1:length(sentword)
    fprintf('%s\t\t%d\t%d\t%f\t%f\n', wordsbi{sentword(s)},...
    cwpos(sentword(s)) , cwneg(sentword(s)), predsent(s), weightsent(s))
    end

    for s = 1:length(sentbi)
    fprintf('%s\t\t%d\t%d\t%f\t%f\n', wordsbi{sentbi(s)},...
    cwpos(sentbi(s)) , cwneg(sentbi(s)), predbi(s), weightbi(s))
    end

    subplot(2,1,1)
    plot(log(cwpos(sentword) ./ cwneg(sentword)) .* weightsent);
    set(gca,'XTickLabel',wordsbi(sentword))
    set(gca,'XTick',1:sentend)

    subplot(2,1,2)
    plot(log(cwpos(sentbi) ./ cwneg(sentbi)) .* weightbi);
    set(gca,'XTickLabel',wordsbi(sentbi))
    set(gca,'XTick',1:sentend+1)
    end
%     predvote(i) = sum(wordSent(nbsentraw));
end

sum(nblbltst == pred)
% sum(nblbltst == (predvote > 0))

% indvoted = (predvote ~= 0);
% sum(nblbltst(indvoted) == (predvote(indvoted)>0))

%
test_sents = allSStr(test_ind);
fid = fopen('../output/nbtestexamplesc.txt','w');
for i = 1:length(test_sents)
    nbsentraw = nbsenttst{i};
    nbsentraw=nbsentraw(nbsentraw>0);
    poslog = sum(pwpos(nbsentraw));
    neglog = sum(pwneg(nbsentraw));

    fprintf(fid,'%s\n', cell2str(test_sents{i}) );
end
fclose(fid);

c = sum(nblbltst == pred)
l = length(pred)
rate = c/l


function EP = updateEP(EP,Offsprings,nEP)
% Update the external population

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

% This function is written by Lucas Farias

    %% Select the non-dominated solutions
    EP = [EP,Offsprings];
    EP = EP(NDSort(EP.objs,1)==1);
    [N,M] = size(EP.objs);

    %% Delete the overcrowded solutions
    Dis = pdist2(EP.objs,EP.objs);
    Dis(logical(eye(length(Dis)))) = inf;
    Del = false(1,N);
    while sum(Del) < N-nEP
        Remain = find(~Del);
        subDis = sort(Dis(Remain,Remain),2);
        [~,worst] = min(prod(subDis(:,1:min(M,length(Remain))),2));
        Del(Remain(worst)) = true;
    end

    EP = EP(~Del);

end


function SO3VF = exp(F)
% overloads |exp(SO3VF)|
%
% Syntax
%   SO3VF = exp(SO3VF)
%
% Input
%  SO3VF - @SO3VectorField
%
% Output
%  SO3VF - @SO3VectorField
%

SO3VF = SO3VectorFieldHandle(@(rot) g(rot),F.SRight,F.SLeft);

function g = g(rot)
g = F.eval(rot);
g = vector3d(exp(g.xyz.'));
end

end


% This demo efficiently computes emd_hat between two random SIFTs
% histograms (3d histograms, see Lowe's paper: "Distinctive image
% features from scale-invariant keypoints" for more detail) where the
% ground distance between the bins is the thresholded sum of orientation and
% spatial distanced.
% emd_hat was described in the paper:
% A Linear Time Histogram Metric for Improved SIFT Matching
% Ofir Pele, Michael Werman
%  ECCV 2008
% The efficient algorithm is described in the paper:
%  Fast and Robust Earth Mover's Distances
%  Ofir Pele, Michael Werman
%  ICCV 2009

clc; close all; clear all;
rand('state',sum(100*clock));

XNBP= 4; % SIFT's X-dimension
YNBP= 4; % SIFT's Y-dimension
NBO= 16; % SIFT's Orientation-dimension
N= XNBP*YNBP*NBO;
thresh= 2;
extra_mass_penalty= -1; % Default of maximum distance
flowType= 3; % Regular flows

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SIFT ground distance matrix computation.
% Note: loops in Matlab are costly.
% However, this should be done only once.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
D= zeros(N,N);
i= 1;
for y1=1:YNBP
    for x1=1:XNBP
        for nbo1=1:NBO

            j= 1;
            for y2=1:YNBP
                for x2=1:XNBP
                    for nbo2=1:NBO
                        D(i,j)= (sqrt((y1-y2)^2 + (x1-x2)^2) + ...
                                 min( [abs(nbo1-nbo2) NBO-abs(nbo1-nbo2)] ));

                        j=j+1;
                    end
                end
            end
            i= i+1;

        end
    end
end
maxDist= max(D(:));
D= min(D,thresh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

P= rand(N,1);
Q= rand(N,1);

% The demo includes several ways to call emd_hat_mex and emd_hat_gd_metric_mex
demo_FastEMD_compute(P,Q,D,extra_mass_penalty,flowType);

% Copyright (c) 2009-2012, Ofir Pele
% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%    * Redistributions of source code must retain the above copyright
%    notice, this list of conditions and the following disclaimer.
%    * Redistributions in binary form must reproduce the above copyright
%    notice, this list of conditions and the following disclaimer in the
%    documentation and/or other materials provided with the distribution.
%    * Neither the name of the The Hebrew University of Jerusalem nor the
%    names of its contributors may be used to endorse or promote products
%    derived from this software without specific prior written permission.

% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
% IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
% THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
% PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


clear; clc;
dataset='SearchSnippets'; %SearchSnippets, StackOverflow, Biomedical
method = 'SVM'; % SVM(Support Vector Machine)
isKernel = 0; %1: SVM Gaussian Kernel; 0: SVM Linear Kernel.
Weighting = 'TF'; %TF, TFIDF or AE(Average Embedding)
dataStr=['./../../dataset/',dataset,'-lite.mat'];
load(dataStr);
rand('state',0)
randn('state',0)
%%
disp('Step 1 get the train and test data ...')
% TFIDF
if (strcmp(Weighting,'TF'))
    testFea = fea(testIdx, :);
    trainFea = fea(trainIdx, :);
    testGnd = gnd(testIdx, :);
    trainGnd = gnd(trainIdx, :);
elseif (strcmp(Weighting,'TFIDF'))
    testFea = fea(testIdx, :);
    trainFea = fea(trainIdx, :);
    testGnd = gnd(testIdx, :);
    trainGnd = gnd(trainIdx, :);
    [trainFea, testFea] = tf_idf_tt(trainFea, testFea);
elseif (strcmp(Weighting,'AE'))
    dataStr=['./../../dataset/',dataset,'-STC2.mat'];
    load(dataStr);
    parameters.wordDim = 48;
    parameters.vocSize = size_vocab;
    disp('AE: Generate verage embedding vectors ...')
    % Step a. Generate word vector sets
    CR_E = randi([-25,25],parameters.wordDim,parameters.vocSize)/100;
    disp(strcat('Number of weights E:',num2str(size(CR_E))));
    vocab_emb_length = length(vocab_emb_Word2vec_48(1,:));
    if vocab_emb_length > size_vocab
        error(['Error, and the size fo vocab_emb is:',vocab_emb_length])
    end
    CR_E(1:parameters.wordDim,vocab_emb_Word2vec_48_index) = vocab_emb_Word2vec_48(1:parameters.wordDim,1:vocab_emb_length);
    % Step b. Average Embedding
    textSize = length(fea_All(:,1));
    fea =[];
    for i=1:textSize
        tmp_fea_vector_weight = repmat(fea_All(i,find(fea_All(i,:)>0)),parameters.wordDim,1);
        tmp_fea_vector_matrix = CR_E(:,find(fea_All(i,:)>0)) .* tmp_fea_vector_weight;
        tmp_fea_vector = sum(tmp_fea_vector_matrix,2);
        fea(i,:) = tmp_fea_vector';
        if mod(i,2000) == 0
            disp(['has averaged embedding number:',num2str(i)]);
        end
    end
    testFea = fea(testIdx, :);
    trainFea = fea(trainIdx, :);
    testGnd = gnd(testIdx, :);
    trainGnd = gnd(trainIdx, :);
    %
end
testFea = normalize(testFea);
trainFea = normalize(trainFea);
%%
disp('step 2 train model ...')
if (strcmp(method,'SVM'))
    trainFea = sparse(trainFea);
    testFea = sparse(testFea);
    if ~isKernel
        disp('start train linear SVM model ...')
        model = train(trainGnd, trainFea, '-q');
        disp('start predict test data via linear SVM ...')
        disp('step 3 predict test data ...')
        [predict_label, accuracy, predict_scores] = predict(testGnd, testFea, model, '-b 1');
    else
        disp('start train kernel SVM model ...')
        model = svmtrain(trainGnd, trainFea, '-t 0');
        disp('start predict test data via kernel SVM model ...')
        disp('step 3 predict test data ...')
        [predict_label, accuracy, predict_scores] = svmpredict(testGnd, testFea, model);
    end
end
AC = length(find(predict_label == testGnd))/length(testGnd)*100;
disp(['Accuracy is ',num2str(AC)])


function value = r4_bide ( x )

%*****************************************************************************80
%
%% R4_BIDE: exponentially scaled derivative, Airy function Bi of an R4 argument.
%
%  Discussion:
%
%    if X < 0,
%      R4_BIDE ( X ) = R4_BID ( X )
%    else
%      R4_BIDE ( X ) = R4_BID ( X ) * exp ( - 2/3 * X^(3/2) )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 October 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real VALUE, the exponentially scaled derivative of
%    the Airy function Bi of X.
%
  persistent atr
  persistent bif2cs
  persistent bifcs
  persistent big2cs
  persistent bigcs
  persistent bip1cs
  persistent bip2cs
  persistent btr
  persistent nbif
  persistent nbif2
  persistent nbig
  persistent nbig2
  persistent nbip1
  persistent nbip2
  persistent x2sml
  persistent x3sml
  persistent x32sml
  persistent xbig

  atr =  8.7506905708484345;
  btr = -2.0938363213560543;

  if ( isempty ( nbif ) )

    bif2cs = [ ...
       0.323493987603522033521E+00, ...
       0.086297871535563559139E+00, ...
       0.002994025552655397426E+00, ...
       0.000051430528364661637E+00, ...
       0.000000525840250036811E+00, ...
       0.000000003561751373958E+00, ...
       0.000000000017146864007E+00, ...
       0.000000000000061663520E+00, ...
       0.000000000000000171911E+00, ...
       0.000000000000000000382E+00 ]';
    bifcs = [ ...
       0.1153536790828570243E+00, ...
       0.0205007894049192875E+00, ...
       0.0002135290278902876E+00, ...
       0.0000010783960614677E+00, ...
       0.0000000032094708833E+00, ...
       0.0000000000062930407E+00, ...
       0.0000000000000087403E+00, ...
       0.0000000000000000090E+00 ]';
    big2cs = [ ...
       1.6062999463621294578E+00, ...
       0.7449088819876088652E+00, ...
       0.0470138738610277380E+00, ...
       0.0012284422062548239E+00, ...
       0.0000173222412256624E+00, ...
       0.0000001521901652368E+00, ...
       0.0000000009113560249E+00, ...
       0.0000000000039547918E+00, ...
       0.0000000000000130017E+00, ...
       0.0000000000000000335E+00 ]';
    bigcs = [ ...
      -0.097196440416443537390E+00, ...
       0.149503576843167066571E+00, ...
       0.003113525387121326042E+00, ...
       0.000024708570579821297E+00, ...
       0.000000102949627731379E+00, ...
       0.000000000263970373987E+00, ...
       0.000000000000458279271E+00, ...
       0.000000000000000574283E+00, ...
       0.000000000000000000544E+00 ]';
    bip1cs = [ ...
      -0.1729187351079553719E+00, ...
      -0.0149358492984694364E+00, ...
      -0.0005471104951678566E+00, ...
       0.0001537966292958408E+00, ...
       0.0000154353476192179E+00, ...
      -0.0000065434113851906E+00, ...
       0.0000003728082407879E+00, ...
       0.0000002072078388189E+00, ...
      -0.0000000658173336470E+00, ...
       0.0000000074926746354E+00, ...
       0.0000000011101336884E+00, ...
      -0.0000000007265140553E+00, ...
       0.0000000001782723560E+00, ...
      -0.0000000000217346352E+00, ...
      -0.0000000000020302035E+00, ...
       0.0000000000019311827E+00, ...
      -0.0000000000006044953E+00, ...
       0.0000000000001209450E+00, ...
      -0.0000000000000125109E+00, ...
      -0.0000000000000019917E+00, ...
       0.0000000000000015154E+00, ...
      -0.0000000000000004977E+00, ...
       0.0000000000000001155E+00, ...
      -0.0000000000000000186E+00 ]';
    bip2cs = [ ...
      -0.13269705443526630495E+00, ...
      -0.00568443626045977481E+00, ...
      -0.00015643601119611610E+00, ...
      -0.00001136737203679562E+00, ...
      -0.00000143464350991284E+00, ...
      -0.00000018098531185164E+00, ...
       0.00000000926177343611E+00, ...
       0.00000001710005490721E+00, ...
       0.00000000476698163504E+00, ...
      -0.00000000035195022023E+00, ...
      -0.00000000058890614316E+00, ...
      -0.00000000006678499608E+00, ...
       0.00000000006395565102E+00, ...
       0.00000000001554529427E+00, ...
      -0.00000000000792397000E+00, ...
      -0.00000000000258326243E+00, ...
       0.00000000000121655048E+00, ...
       0.00000000000038707207E+00, ...
      -0.00000000000022487045E+00, ...
      -0.00000000000004953477E+00, ...
       0.00000000000004563782E+00, ...
       0.00000000000000332998E+00, ...
      -0.00000000000000921750E+00, ...
       0.00000000000000094157E+00, ...
       0.00000000000000167154E+00, ...
      -0.00000000000000055134E+00, ...
      -0.00000000000000022369E+00, ...
       0.00000000000000017487E+00, ...
       0.00000000000000000207E+00 ]';

    eta = 0.1 * r4_mach ( 3 );
    nbif = r4_inits ( bifcs, 8, eta );
    nbig = r4_inits ( bigcs, 9, eta );
    nbif2 = r4_inits ( bif2cs, 10, eta );
    nbig2 = r4_inits ( big2cs, 10, eta );
    nbip1 = r4_inits ( bip1cs, 24, eta );
    nbip2 = r4_inits ( bip2cs, 29, eta );
    x2sml = sqrt ( eta );
    x3sml = eta^0.3333;
    x32sml = 1.3104 * x3sml * x3sml;
    xbig = r4_mach ( 2 )^0.6666;

  end

  if ( x <= - 1.0 )
    [ xn, phi ] = r4_admp ( x );
    value = xn * sin ( phi );
  elseif ( 0.0 <= x && x <= x32sml )
    x2 = 0.0;
    x3 = 0.0;
    value = x2 * ( r4_csevl ( x3, bifcs, nbif ) + 0.25 ) ...
      + r4_csevl ( x3, bigcs, nbig ) + 0.5;
  elseif ( abs ( x ) <= x2sml )
    x2 = 0.0;
    x3 = 0.0;
    value = x2 * ( r4_csevl ( x3, bifcs, nbif ) + 0.25 ) ...
      + r4_csevl ( x3, bigcs, nbig ) + 0.5;
    value = value * exp ( - 2.0 * x * sqrt ( x ) / 3.0 );
  elseif ( x <= x3sml )
    x2 = x * x;
    x3 = 0.0;
    value = x2 * ( r4_csevl ( x3, bifcs, nbif ) + 0.25 ) ...
      + r4_csevl ( x3, bigcs, nbig ) + 0.5;
    value = value * exp ( - 2.0 * x * sqrt ( x ) / 3.0 );
  elseif ( x <= 1.0 )
    x2 = x * x;
    x3 = x * x * x;
    value = x2 * ( r4_csevl ( x3, bifcs, nbif ) + 0.25 ) ...
      + r4_csevl ( x3, bigcs, nbig ) + 0.5;
    value = value * exp ( - 2.0 * x * sqrt ( x ) / 3.0 );
  elseif ( x <= 2.0 )
    z = ( 2.0 * x * x * x - 9.0 ) / 7.0;
    value = exp ( - 2.0 * x * sqrt ( x ) / 3.0 ) ...
      * ( x * x * ( 0.25 + r4_csevl ( z, bif2cs, nbif2 ) ) ...
      + 0.5 + r4_csevl ( z, big2cs, nbig2 ) );
  elseif ( x <= 4.0 )
    sqrtx = sqrt ( x );
    z = atr / ( x * sqrtx ) + btr;
    value = ( 0.625 ...
      + r4_csevl ( z, bip1cs, nbip1 ) ) * sqrt ( sqrtx );
  elseif ( x < xbig )
    sqrtx = sqrt ( x );
    z = 16.0 / ( x * sqrtx ) - 1.0;
    value = ( 0.625 + r4_csevl ( z, bip2cs, nbip2 ) ) ...
      * sqrt ( sqrtx );
  else
    sqrtx = sqrt ( x );
    z = - 1.0;
    value = ( 0.625 + r4_csevl ( z, bip2cs, nbip2 ) ) * sqrt ( sqrtx );
  end

  return
end