function [k, sk, skIC] = heatKernDiagCompute(heatKern, x)

% HEATKERNDIAGCOMPUTE Diagonal of a kernel matrix for a HEAT kernel.
% DESC computes the diagonal of the kernel matrix for the HEAT kernel
% given a design matrix of inputs.
% ARG kern : the kernel structure for which the matrix is computed.
% ARG x : input data matrix in the form of a design matrix.
% RETURN k : a vector containing the diagonal of the kernel matrix
% computed at the given points.
% RETURN sk : unscaled version of the diagonal.
% RETURN sk : unscaled version of the diagonal for the kernel matrix of the
% initial conditions.
%
% SEEALSO : heatKernParamInit, kernDiagCompute, kernCreate, heatKernCompute
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

if size(x, 2) ~= 2
    error('Input can only have two columns');
end

option = 'cos';

if strcmp(option, 'cos')
    [k, sk] = heatXheatKernCompute(heatKern, heatKern, x, x);
    k = diag(k);
    sk = diag(sk);
else
    % Split the domain into time domain and spatial domain and account for
    % missing values. If there are no missing values the computation of the
    % kernel is a pointwise prodruct, otherwise it is a kronecker product.
    t = x(x(:,1)~=Inf,1);
    s = x(x(:,2)~=Inf,2);

    if (length(t) == length(s))
        ut = unique(t);
        us = unique(s);
        if (length(ut)*length(us) == length(t))
            t = ut;
            s = us;
            isPointwise = false;
            sk = zeros(length(t)*length(s), 1);
            if heatKern.includeIC
                skIC = zeros(length(t)*length(s), 1);
            end
        else
            isPointwise = true;
            sk = zeros(length(t), 1);
            if heatKern.includeIC
                skIC = zeros(length(t), 1);
            end
        end
    else
        isPointwise = false;
        sk = zeros(length(t)*length(s), 1);
        if heatKern.includeIC
            skIC = zeros(length(t)*length(s), 1);
        end
    end

    % Although this is done in heatKernExpandParam.m, we do it here again as a
    % precaution.

    heatKern.sim.inverseWidth = heatKern.inverseWidthTime;

    sigmax  = sqrt(2/heatKern.inverseWidthSpace);
    lengthX = heatKern.lengthX;
    nterms  = heatKern.nTerms;
    decay   = heatKern.decay;
    diff    = heatKern.diffusion;

    % Precompute some terms
    w = ((1:nterms)*(pi/lengthX))';
    gamma = sqrt(-1)*w;
    beta = decay + diff*(w.^2);
    z1 = sigmax*gamma/2;
    z2 = lengthX/sigmax + z1;
    wz1 = wofzPoppe(sqrt(-1)*z1);
    wz2 = wofzPoppe(sqrt(-1)*z2);
    cK = 4/(lengthX^2);

    simLocal = heatKern.sim;

    if heatKern.includeIC
        sigmah = sqrt(2/heatKern.inverseWidthSpaceIC);
        z1h = sigmah*gamma/2;
        z2h = lengthX/sigmah + z1h;
        wz1h = wofzPoppe(sqrt(-1)*z1h);
        wz2h = wofzPoppe(sqrt(-1)*z2h);
        if isPointwise
            for i=1:nterms
                heatKern.sim.decay = beta(i);
                kt = simKernDiagCompute(heatKern.sim, t);
                ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, i);
                ktIC = exp(-2*beta(i)*t);
                ksIC = sheatKernDiagCompute(sigmah, lengthX, s, w, gamma, wz1h, wz2h, i, i);
                skIC = skIC + ktIC.*ksIC;
                sk = sk + kt.*ks;
                for j=1:i-1
                    if (mod(i+j,2)==0)
                        heatKern.sim.decay = beta(i);
                        simLocal.decay = beta(j);
                        %kt = diag(simXsimKernCompute(heatKern.sim, simLocal, t, t));
                        kt = simXsimKernDiagCompute(heatKern.sim, simLocal, t);
                        ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, j);
                        ktIC = exp(-(beta(i)+beta(j))*t);
                        ksIC = sheatKernDiagCompute(sigmah, lengthX, s, w, gamma, wz1h, wz2h, i, j);
                        skIC = skIC + 2*ktIC.*ksIC;
                        sk = sk + 2*kt.*ks;
                    end
                end
            end
        else
            for i=1:nterms
                heatKern.sim.decay = beta(i);
                kt = simKernDiagCompute(heatKern.sim, t);
                ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, i);
                ktIC = exp(-2*beta(i)*t);
                ksIC = sheatKernDiagCompute(sigmah, lengthX, s, w, gamma, wz1h, wz2h, i, i);
                skIC = skIC + kron(ktIC, ksIC);
                sk = sk + kron(kt, ks);
                for j=1:i-1
                    if (mod(i+j,2)==0)
                        heatKern.sim.decay = beta(i);
                        simLocal.decay = beta(j);
                        %kt = diag(simXsimKernCompute(heatKern.sim, simLocal, t, t));
                        kt = simXsimKernDiagCompute(heatKern.sim, simLocal, t);
                        ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, j);
                        ktIC = exp(-(beta(i)+beta(j))*t);
                        ksIC = sheatKernDiagCompute(sigmah, lengthX, s, w, gamma, wz1h, wz2h, i, j);
                        skIC = skIC + 2*kron(ktIC, ksIC);
                        sk = sk + 2*kron(kt, ks);
                    end
                end
            end
        end
        sk = cK*sk;
        skIC = cK*skIC;
        k = (heatKern.sensitivity^2)*sk + (heatKern.sensitivityIC^2)*skIC;
    else
        if isPointwise
            for i=1:nterms
                heatKern.sim.decay = beta(i);
                kt = simKernDiagCompute(heatKern.sim, t);
                ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, i);
                sk = sk + kt.*ks;
                for j=1:i-1
                    if (mod(i+j,2)==0)
                        heatKern.sim.decay = beta(i);
                        simLocal.decay = beta(j);
                        %kt = diag(simXsimKernCompute(heatKern.sim, simLocal, t, t));
                        kt = simXsimKernDiagCompute(heatKern.sim, simLocal, t);
                        ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, j);
                        sk = sk + 2*kt.*ks;
                    end
                end
            end
        else
            for i=1:nterms
                heatKern.sim.decay = beta(i);
                kt = simKernDiagCompute(heatKern.sim, t);
                ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, i);
                sk = sk + kron(kt, ks);
                for j=1:i-1
                    if (mod(i+j,2)==0)
                        heatKern.sim.decay = beta(i);
                        simLocal.decay = beta(j);
                        %kt = diag(simXsimKernCompute(heatKern.sim, simLocal, t, t));
                        kt = simXsimKernDiagCompute(heatKern.sim, simLocal, t);
                        ks = sheatKernDiagCompute(sigmax, lengthX, s, w, gamma, wz1, wz2, i, j);
                        sk = sk + kron(2*kt, ks);
                    end
                end
            end
        end
        sk = cK*sk;
        k = (heatKern.sensitivity^2)*sk;
        if nargin > 2
            skIC = 0;
        end
    end
end

k = real(k);
sk = real(sk);


%==============================================================================
% 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 P = nodal2center(y,m,mex)
%
% transfers a nodal grid to a cell-centered grid
% if nargin==1, builds P explicitely, else return results of P(y), matrix free; endif
% depending on numel(Y), the matrix free version also handles P'(Y)
%
% Input:
%   y        input points,  nodal or cell-centered
%   m        number of discretization points
%   mex      bool (use mex code for matrix-free implementation)
%
% Output:
%   P        the projection matrix P, if nargin == 2
%            P*y,                     if y is nodal
%            P'*y,                    if y is cell-centered
%==============================================================================

function P = nodal2center(y,m,mex)

if nargin == 0 % help and minimal example
  help(mfilename);
  runMinimalExample;
  P = 'endMinimalExample';
  return
end

Js = {[1 2 3], [2 1 3], [3 1 2]}; % different permutations of dimensions

if nargin==1, m = y; end
dim = length(m);

% Here starts the matrix-based code
if nargin==1
  % ----------------------------------
  % build the matrix P and return it
  % ----------------------------------
  av = @(i) spdiags(ones(m(i),1)*[ 1,1],[0,1],m(i),m(i)+1)/2;
  zero = sparse(prod(m),prod(m+1));
  switch dim
    case 2
      A = kron(av(2), av(1));
      P = sparse([A zero; zero A]);
    case 3
      A = kron(av(3), kron(av(2), av(1)));
      P = sparse([A zero zero; zero A zero; zero zero A]);
    otherwise
      error('Dimension must be either 2 or 3.')
  end
  return; % end of story
end

% Here starts the MEX based code
if (dim > 1) && exist(fullfile(FAIRpath,'kernel',[mfilename,'C.',mexext])) == 3,
  if numel(y) == length(m)*prod(m)
    % cell-centered ->  nodal
    status = true;
  else
    % nodal -> cell-centered
    status = false;
  end;
  P = nodal2centerC(y, m, dim, status);
  return;
end;

% Here starts the matrix-free code

if numel(y) == length(m)*prod(m)
  % -----------------------
  % cell-centered ->  nodal
  % -----------------------
  y = reshape(y,prod(m),[]);
  Z = zeros(prod(m+1),size(y,2));         % allocate memory
  for i=1:size(y,2)                       % run over all components of Y
    yi = reshape(y(:,i),m);
    for j=1:dim                           % run over all dimensions in yi
      % J = [j,setdiff(1:dim,j)];         % make j-th dimension first
      J = Js{j};                          % make j-th dimension first
      yi = permute(yi,J);

      zi = yi([1 1:end],:,:);
      zi(2:end-1,:,:) = zi(2:end-1,:,:) + yi(2:end,:,:);

      yi = .5* ipermute(zi,J);            % undo permutation
    end
    Z(:,i) = yi(:);                       % store i-th component
  end
else
  % -----------------------
  % nodal -> cell-centered
  % -----------------------
  % MATLAB implementation
  y = reshape(y,prod(m+1),[]);
  Z = zeros(prod(m),size(y,2));           % allocate memory
  for i=1:size(y,2)                       % run over all components of Y
    if dim==1                             % 1D case is simplr and does not admit oermutations
      P = 0.5*(y(1:end-1)+y(2:end));
      return
    else
      yi = reshape(y(:,i),m+1);           % reorganize Y
    end
    for j=1:dim                           % run over all dimensions in yi
      % J = [j,setdiff(1:dim,j)];         % make j-th dimension first
      J = Js{j};                          % make j-th dimension first
      yi = permute(yi,J);
      % average nodal to center
      yi = 0.5*(yi(1:end-1,:,:)+yi(2:end,:,:));
      yi = ipermute(yi,J);                % undo permutation
    end
    Z(:,i) = reshape(yi,[],1);            % store i-th component
  end

end
P = reshape(Z,[],1);                      % reshape
%------------------------------------------------------------------------------

function runMinimalExample

omega = [0 2 0 1];
m     = [8,7];
yn    = getNodalGrid(omega,m);
xc    = nodal2center(yn,m);
xc    = reshape(xc,[],2);

FAIRfigure(1); clf;
subplot(2,1,1); spy(nodal2center([4,5,6])); title('spy(nodal2gcenter operator)');
subplot(2,1,2); plotGrid(yn,omega,m,'color','b'); hold on; plot(xc(:,1),xc(:,2),'rx');
title(mfilename);

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


function varargout = process_zscore_ab( varargin )
% PROCESS_ZSCORE: Compute Z-Score for a matrix A (normalization respect to a baseline).
%
% DESCRIPTION:  For each channel:
%     1) Compute mean m and variance v for baseline
%     2) For each time sample, subtract m and divide by v

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2012-2015

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Z-score static (A=baseline) [DEPRECATED]';
    sProcess.FileTag     = 'zscore';
    sProcess.Category    = 'Filter2';
    sProcess.SubGroup    = 'Standardize';
    sProcess.Index       = 0;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/SourceEstimation#Z-score';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data', 'results', 'timefreq', 'matrix'};
    sProcess.OutputTypes = {'data', 'results', 'timefreq', 'matrix'};
    sProcess.nInputs     = 2;
    sProcess.nMinFiles   = 1;
    % Default values for some options
    sProcess.isSourceAbsolute = 0;
    sProcess.processDim       = 1;    % Process channel by channel
    sProcess.isPaired         = 1;

    % Definition of the options
    sProcess.options.description.Comment = ['For each signal in input:
' ...
                                            '1) FilesA: Compute mean m and variance v for the baseline
' ...
                                            '2) FilesB: For each time sample, subtract m and divide by v
' ...
                                            'Z = (Data - m) / v

'];
    sProcess.options.description.Type    = 'label';
    % === Baseline time window
    sProcess.options.baseline.Comment = 'Baseline (Files A):';
    sProcess.options.baseline.Type    = 'baseline';
    sProcess.options.baseline.Value   = [];
    % === Sensor types
    sProcess.options.sensortypes.Comment = 'Sensor types or names (empty=all): ';
    sProcess.options.sensortypes.Type    = 'text';
    sProcess.options.sensortypes.Value   = 'MEG, EEG';
    sProcess.options.sensortypes.InputTypes = {'data'};
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    % Get frequency band
    if isfield(sProcess.options, 'baseline') && isfield(sProcess.options.baseline, 'Value') && iscell(sProcess.options.baseline.Value) && ~isempty(sProcess.options.baseline.Value) && ~isempty(sProcess.options.baseline.Value{1})
        Time = sProcess.options.baseline.Value{1};
    else
        Time = [];
    end
    % Add frequency band
    if isempty(Time)
        Comment = 'Z-score normalization: [All file]';
    elseif any(abs(Time) > 2)
        Comment = sprintf('Z-score normalization (static): [%1.3fs,%1.3fs]', Time(1), Time(2));
    else
        Comment = sprintf('Z-score normalization (static): [%dms,%dms]', round(Time(1)*1000), round(Time(2)*1000));
    end
end

%% ===== RUN =====
function sInputB = Run(sProcess, sInputA, sInputB) %#ok<DEFNU>
    % Get options
    if isfield(sProcess.options, 'baseline') && isfield(sProcess.options.baseline, 'Value') && iscell(sProcess.options.baseline.Value) && ~isempty(sProcess.options.baseline.Value) && ~isempty(sProcess.options.baseline.Value{1})
        BaselineBounds = sProcess.options.baseline.Value{1};
    else
        BaselineBounds = [];
    end
    % Get baseline indices
    if ~isempty(BaselineBounds)
        iBaseline = bst_closest(sProcess.options.baseline.Value{1}, sInputA.TimeVector);
        if (iBaseline(1) == iBaseline(2)) && any(iBaseline(1) == sInputA.TimeVector)
            error('Invalid baseline definition.');
        end
        iBaseline = iBaseline(1):iBaseline(2);
    % Get all file
    else
        iBaseline = 1:size(sInputA.A,2);
    end
    % Compute zscore
    sInputB.A = Compute(sInputA.A(:,iBaseline,:), sInputB.A);
    % Change DataType
    if ~strcmpi(sInputB.FileType, 'timefreq')
        sInputB.DataType = 'zscore';
    end
    % Default colormap
    if strcmpi(sInputB.FileType, 'results')
        sInputB.ColormapType = 'stat1';
        sInputB.Function = 'zscore';
    else
        sInputB.ColormapType = 'stat2';
    end
end

%% ===== COMPUTE =====
function B_data = Compute(A_baseline, B_data)
    disp('BST> process_zscore_ab.m is deprecated, use "Standardize > Baseline normalization" instead.');
    % Calculate mean and standard deviation
    [meanBaseline, stdBaseline] = process_zscore('ComputeStat', A_baseline);
    % Compute zscore
    B_data = bst_bsxfun(@minus, B_data, meanBaseline);
    B_data = bst_bsxfun(@rdivide, B_data, stdBaseline);
end


clear all; close all; clc;

% The matrix to be displayed.
data = spiral(100);

spx.graphics.display.matrix(data);

data = randn(100, 100);
options.color_map = 'gray';
spx.graphics.display.matrix(data, options);


% ASIN   Inverse sine, result in radians.
%    ASIN(X) is the arcsine of the elements of X. Complex
%    results are obtained if ABS(x) > 1.0 for some element.
%
%    See also SIN, ASIND.
%
%    Reference page in Doc Center
%       doc asin
%
%    Other functions named asin
%
%       codistributed/asin    gpuArray/asin    sym/asin    ts/asin
%


function R = strsimilarity(a,b)
%STRSIMILARITY Similarity measure between two character vectors.
%   R = STRSIMILARITY(A,B) computes the similarity measure, R, defined
%   in Eq. (14-22) between character vectors A and B. The vectors do not
%   have to be of the same length, but they should be otherwise
%   registered for this method to make sense. All blanks in both vectors
%   are deleted, so they should not be used as valid characters in
%   defining A and B. Inputs can be either character vectors or scalar
%   strings, in the sense defined by MATLAB. If the inputs are strings
%   they are converted to character vectors.
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

% If inputs are scalar strings, covert them to character vectors. If
% they already are character vectors, they are not affected by the
% following function.
if (isstring(a) && isstring(b)) || (ischar(a) && ischar(b))
   a = convertStringsToChars(a);
   b = convertStringsToChars(b);
else
   error('a and b must both character vectors or both be strings')
end

% Make sure the inputs are character vectors and not higher-dimensional
% character arrays.
if ~(size(a,1) == 1 || size(a,2) == 1) && ~(size(b,1) == 1 ||...
                                                         size(b,2) == 1)
   error('a and b must be character vectors')
end

% Make sure they are rows for dimensional consistency later on.
a = a(:)';
b = b(:)';

% Remove all blanks.
a = a(~isspace(a));
b = b(~isspace(b));

% Pad the end of the shorter string.
La = length(a);
Lb = length(b);
if La > Lb
   b = [b,blanks(La - Lb)];
else
   a = [a,blanks(Lb - La)];
end

% Compute the similarity measure.
I = find(a == b);
alpha = numel(I);
den = max(La,Lb) - alpha;
R = alpha/den;


 function yy = ir_imfill1(xx)
%function yy = ir_imfill1(xx)
%|
%| 1D version of imfill 'holes' that works along 1st dimension of input
%|
%| in
%| xx [N (L)]	logical array
%| out
%| yy [N (L)]	logical array
%|
%| 2015-08-13, Jeff Fessler, University of Michigan

if nargin < 1, ir_usage, end
if streq(xx, 'test'), ir_imfill1_test, return, end

if ~islogical(xx), fail('input must be logical'), end

yy = cummax(xx,1) & flipdim(cummax(flipdim(xx,1),1),1);

function ir_imfill1_test
x = ellipse_im(64) > 0;
x(end/2,end/4+[1:5]) = 0;
y1 = ir_imfill1(x);
y2 = ir_imfill1(x')';
im plc 2 2
im(1, x)
im(2, y1)
im(3, y2)
im(4, y2-y1)


function facenb=faceneighbors(t,opt)
%
% facenb=faceneighbors(t,opt)
%
% to find 4 face-neighboring elements of a tetrahedron
%
% author: Qianqian Fang, <q.fang at neu.edu>
%
% input:
%     t: tetrahedron element list, 4 columns of integers
%     opt: if opt='surface', return boundary triangle list
%          (should be the same as the face output from v2m)
%          if opt='rowmajor', same as 'surface', except the
%          order of the triangles are in the row-major order
%%
%          otherwise, return the element list for each element:
%          each row contains 4 numbers, representing the element
%          indices sharing triangular faces [1 2 3],[1 2 4],[1 3 4]
%          and [2 3 4] in order, where 1~4 is the node local index.
%          if the index is 0, indicating the face has no neighbor
%          (i.e. a boundary face)
%
% output:
%     facenb: see opt
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

faces=[t(:,[1,2,3]);
       t(:,[1,2,4]);
       t(:,[1,3,4]);
       t(:,[2,3,4])];

faces=sort(faces,2);
[foo,ix,jx]=unique(faces,'rows');
if(isoctavemesh)
        u=unique(jx);
        qx=u(hist(jx,u)==2);
else
        vec=histc(jx,1:max(jx));
        qx=find(vec==2);
end

nn=max(t(:));
ne=size(t,1);
facenb=zeros(size(t));

% now I need to find all repeatitive elements
% that share a face, to do this, unique('first')
% will give me the 1st element, and 'last' will
% give me the second. There will be no more than 2

% doing this is 60 times faster than doing find(jx==qx(i))
% inside a loop

if(isoctavemesh || datenum(version('-date'))>datenum('January 27 2006')) % compare to matlab 7.2
	[ujx,ii]=unique(jx,'first');
	[ujx,ii2]=unique(jx,'last');
else
	ujx=unique(jx);
	[t1,ii2]=ismember(ujx,jx);
	[t1,ii]=ismember(ujx,flipwd(jx(:)));
	ii=length(jx)-ii+1;
end

% iddup is the list of all pairs that share a common face

iddup=[ii(qx) ii2(qx)];
faceid=ceil(iddup/ne);
eid=mod(iddup,ne);
eid(eid==0)=ne;

% now rearrange this list into an element format

for i=1:length(qx)
	facenb(eid(i,1),faceid(i,1))=eid(i,2);
	facenb(eid(i,2),faceid(i,2))=eid(i,1);
end

% facenb may contain 0s, that just means the corresponding
% face is a boundary face and has no neighbor.

% if the second option is 'surface', I am going to find
% and return surface patches only

if(nargin==2)
  if(strcmp(opt,'surface'))
	facenb=faces(find(facenb==0),:);
  elseif(strcmp(opt,'rowmajor'))
	index=[1:length(faces)];
	index=(reshape(index,[],4))';
	faces=faces(index(:),:);
	facenb=faces(find(facenb'==0),:);
  else
        error(['supplied option "' opt '" is not supported.']);
  end
end


function outputImage = edge(this, method, thresh)
% Computes edges of a 3D or 4D image per 2D-slice
%
%   Y = MrImage()
%   outputImage = edge(Y, method, thresh)
%
% This is a method of class MrImage.
%
% IN
%   method      'sobel', 'roberts', 'prewitt' See also edge
%   thresh      custom threshold for edge detection; default: [] determines
%               threshold automatically
% OUT
%   outputImage binary image with detection edges == 1
%
% EXAMPLE
%   edgeY = Y.edge('prewitt', 300);
%
%   See also MrImage perform_unary_operation

% Author:   Saskia Bollmann & Lars Kasper
% Created:  2014-11-25
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC 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/>.

if nargin < 2
    method = 'sobel';
end

if nargin < 3
    thresh = [];
end

if isreal(this)
    outputImage = this.perform_unary_operation(...
        @(X) edge(X, method, thresh), '2D');
else % perform on abs for complex data
    outputImage = this.abs.perform_unary_operation(...
        @(X) edge(X, method, thresh), '2D');
end


function sphere_cubed_grid_points_display_test ( )

%*****************************************************************************80
%
%% SPHERE_CUBED_GRID_POINTS_DISPLAY_TEST tests SPHERE_CUBED_GRID_POINTS_DISPLAY.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 May 2015
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SPHERE_CUBED_GRID_POINTS_DISPLAY_TEST\n' );
  fprintf ( 1, '  SPHERE_CUBED_GRID_POINTS_DISPLAY_TEST displays points\n' );
  fprintf ( 1, '  on a cubed sphere grid.\n' );

  n = 10;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of divisions on each face = %d\n', n );

  ns = sphere_cubed_grid_point_count ( n );
  fprintf ( 1, '  Total number of points = %d\n', ns );

  xyz = sphere_cubed_grid_points ( n, ns );

  filename = sprintf ( 'sphere_cubed_grid_points_f%d.png', n );

  sphere_cubed_grid_points_display ( ns, xyz, filename );

  return
end


function [L, S] = quasi2diffmat(disc)
%QUASI2USDIFFMAT(DISC)   Convert DISC.coeffs to a differential operator.
%   L = QUASI2USDIFFMAT(DISC) returns a matrix L corresponding to the
%   differential operator C{1}*D^[m] + ... C{m+1}*I.
%
% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Get info from DISC:
c = fliplr(disc.coeffs);
if ( isempty(disc.outputSpace) )
    disc.outputSpace = size(c, 2) - 1;
end
dim = disc.dimension;

L = sparse(sum(dim), sum(dim));
for j = 1:size(c, 2)
    L = L + mult(disc, c{j}) * diff(disc, j - 1);
end

if ( nargout > 1 )
    S = [];
end

end


function B = boundaries(BW, conn, dir)
%BOUNDARIES Trace object boundaries.
%   B = BOUNDARIES(BW) traces the exterior boundaries of objects in
%   the binary image BW.  B is a P-by-1 cell array, where P is the
%   number of objects in the image. Each cell contains a Q-by-2
%   matrix, each row of which contains the row and column coordinates
%   of a boundary pixel.  Q is the number of boundary pixels for the
%   corresponding object.  Object boundaries are traced in the
%   clockwise direction.
%
%   B = BOUNDARIES(BW, CONN) specifies the connectivity to use when
%   tracing boundaries.  CONN may be either 8 or 4.  The default
%   value for CONN is 8.
%
%   B = BOUNDARIES(BW, CONN, DIR) specifies the direction used for
%   tracing boundaries.  DIR should be either 'cw' (trace boundaries
%   clockwise) or 'ccw' (trace boundaries counterclockwise).  If DIR
%   is omitted BOUNDARIES traces in the clockwise direction.

%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.6 $  $Date: 2003/11/21 14:22:07 $

if nargin < 3
   dir = 'cw';
end

if nargin < 2
   conn = 8;
end

L = bwlabel(BW, conn);

% The number of objects is the maximum value of L.  Initialize the
% cell array B so that each cell initially contains a 0-by-2 matrix.
numObjects = max(L(:));
if numObjects > 0
   B = {zeros(0, 2)};
   B = repmat(B, numObjects, 1);
else
   B = {};
end

% Pad label matrix with zeros.  This lets us write the
% boundary-following loop without worrying about going off the edge
% of the image.
Lp = padarray(L, [1 1], 0, 'both');

% Compute the linear indexing offsets to take us from a pixel to its
% neighbors.
M = size(Lp, 1);
if conn == 8
   % Order is N NE E SE S SW W NW.
   offsets = [-1, M - 1, M, M + 1, 1, -M + 1, -M, -M-1];
else
   % Order is N E S W.
   offsets = [-1, M, 1, -M];
end

% next_search_direction_lut is a lookup table.  Given the direction
% from pixel k to pixel k+1, what is the direction to start with when
% examining the neighborhood of pixel k+1?
if conn == 8
   next_search_direction_lut = [8 8 2 2 4 4 6 6];
else
   next_search_direction_lut = [4 1 2 3];
end

% next_direction_lut is a lookup table.  Given that we just looked at
% neighbor in a given direction, which neighbor do we look at next?
if conn == 8
   next_direction_lut = [2 3 4 5 6 7 8 1];
else
   next_direction_lut = [2 3 4 1];
end

% Values used for marking the starting and boundary pixels.
START    = -1;
BOUNDARY = -2;

% Initialize scratch space in which to record the boundary pixels as
% well as follow the boundary.
scratch = zeros(100, 1);

% Find candidate starting locations for boundaries.
[rr, cc] = find((Lp(2:end-1, :) > 0) & (Lp(1:end-2, :) == 0));
rr = rr + 1;

for k = 1:length(rr)
   r = rr(k);
   c = cc(k);
   if (Lp(r,c) > 0) & (Lp(r - 1, c) == 0) & isempty(B{Lp(r, c)})
      % We've found the start of the next boundary.  Compute its
      % linear offset, record which boundary it is, mark it, and
      % initialize the counter for the number of boundary pixels.
      idx = (c-1)*size(Lp, 1) + r;
      which = Lp(idx);

      scratch(1) = idx;
      Lp(idx) = START;
      numPixels = 1;
      currentPixel = idx;
      initial_departure_direction = [];

      done = 0;
      next_search_direction = 2;
      while ~done
         % Find the next boundary pixel.
         direction = next_search_direction;
         found_next_pixel = 0;
         for k = 1:length(offsets)
            neighbor = currentPixel + offsets(direction);
            if Lp(neighbor) ~= 0
               % Found the next boundary pixel.

               if (Lp(currentPixel) == START) & ...
                      isempty(initial_departure_direction)
                  % We are making the initial departure from
                  % the starting pixel.
                  initial_departure_direction = direction;

               elseif (Lp(currentPixel) == START) & ...
                      (initial_departure_direction == direction)
                  % We are about to retrace our path.
                  % That means we're done.
                  done = 1;
                  found_next_pixel = 1;
                  break;
               end

               % Take the next step along the boundary.
               next_search_direction = ...
                   next_search_direction_lut(direction);
               found_next_pixel = 1;
               numPixels = numPixels + 1;
               if numPixels > size(scratch, 1)
                  % Double the scratch space.
                  scratch(2*size(scratch, 1)) = 0;
               end
               scratch(numPixels) = neighbor;

               if Lp(neighbor) ~= START
                  Lp(neighbor) = BOUNDARY;
               end

               currentPixel = neighbor;
               break;
            end

            direction = next_direction_lut(direction);
         end

         if ~found_next_pixel
            % If there is no next neighbor, the object must just
            % have a single pixel.
            numPixels = 2;
            scratch(2) = scratch(1);
            done = 1;
         end
      end

      % Convert linear indices to row-column coordinates and save
      % in the output cell array.
      [row, col] = ind2sub(size(Lp), scratch(1:numPixels));
      B{which} = [row - 1, col - 1];
   end
end

if strcmp(dir, 'ccw')
   for k = 1:length(B)
      B{k} = B{k}(end:-1:1, :);
   end
end


function q1 = rdivide(q1,d)
% scalar division

if isa(q1,'quaternion')
    if isa(d,'double')
      q1.a = q1.a ./ d;
      q1.b = q1.b ./ d;
      q1.c = q1.c ./ d;
      q1.d = q1.d ./ d;
    else
        error('Second argument must be double');
    end
else
    error('First argument must be Quaternion');
end


function [Model, Info] = linear_sparse_stepwise(X,Y,Model,parm)
%  Estimate linear weight matrix for input-output mapping
%     Automatic Relevance Prior for each input dimension
%     is imposed to get sparse weight matrix
%
% Notice !!
%     Delay embedding is done in this module,
%     then input vector should be original input data without embedding
%
%   [Model, Info] = linear_sparse_stepwise(X,Y,Model,parm)
%     Scalar iteration version
% --- Input
%  Y  : Output data ( N x T x Ntrial )
%  X  : Input data  ( M x (T + (Dtau-1)*Tau)  x Ntrial)
%  N  =  # of output
%  M  =  # of input (original input space dimension)
%  T  =  # of time sample
%
%  Estimate the following model
%    Y(t) = W * [X(:, t + (Dtau-1)*Tau ); ...; X(:, t)]
%
%  Model : Structure for estimated model
%  if Model is empty, initialization is done before training
%  if Model is previous training result, re-training us done
%
%  parm  : Structure for learning parameter
%  parm.Npre_train :  # of VB-update in initial training
%  parm.Ntrain :  # of training
%  parm.Nskip  :  skip # for print
%  parm.a_min  :  Min value for pruning small variance component
%  parm.Prune  :  = 1 : Prune small variance & irrelevant input dimension
%
%  parm.Tau       = Lag time
%  parm.Dtau      = Number of embedding dimension
%    Total input dimension in embedding space is (M * parm.Dtau)
% --- Output
%  Model : Structure for estimated model
%  Model.SY  :  Noise variance         ( 1 x 1 )
%  Model.W   :  Weight matrix          ( N x M*D ) , D = parm.Dtau
%  Model.A   :  Prior weight variance  ( 1 x M*D )
%  Model.ix_act : Active index for W after pruning
%
%  Info  : Structure for learning process history
%  Info.FE  = LP + H : Free energy
%  Info.LP  = Log likelihood
%  Info.H   = - Model entropy
%
% 2009-10-18 Made by M. Sato

MINVAL = 1.0e-15;

fprintf('linear_sparse_stepwise start\n')

% Dimension
[N ,T  ,Ntrial]  = size(Y); % N = # of output
[M ,Tx ,Ntrialx] = size(X); % M = # of input without embedding

% Number of samples for each trial
if isfield(parm,'Trial'),
	Trial = parm.Trial;
	if length(Trial) ~= Ntrial, error('Trial sample seting is wrong');end
	if max(Trial) > T, error('Trial sample seting is wrong');end
else
	Trial = repmat(T, [Ntrial 1]);
end
% Set valid sample flag for each trial
trial_sw = zeros(N,T,Ntrial);
for n = 1:Ntrial
	trial_sw(:,1:Trial(n),n) = 1;
end

Tall = sum(Trial);

if Ntrial~=Ntrialx, error('# of trial is different in X and Y'); end;

Nskip  = 100;   % skip steps for display info
a_min = 1e-14;	% Minimum value for weight pruning
Fdiff = 1e-12; % Threshold for convergence
Ncheck = 100;   % Minimum number of training iteration
Fstep  = 5;     % Free energy convergence check step
Prune  = 1;     % Prune mode
space_ARD=1;	% if space_ARD=1, ARD is done only for space dimension

if isfield(parm,'Nskip'), Nskip  = parm.Nskip; end;
if isfield(parm,'Fdiff'), Fdiff   = parm.Fdiff; end;
if isfield(parm,'a_min'), a_min   = parm.a_min ; end;
if isfield(parm,'Prune'), Prune = parm.Prune; end;
if isfield(parm,'Ncheck'), Ncheck = parm.Ncheck; end
if isfield(parm,'Fstep'),Fstep  = parm.Fstep ; end
if isfield(parm,'Fstep'),Fstep  = parm.Fstep ; end
if isfield(parm,'space_ARD'),space_ARD  = parm.space_ARD ; end

% # of embedding dimension
if isfield(parm,'Dtau')
	D    = parm.Dtau;
	tau  = parm.Tau;
else
	D    = 1;
	tau  = 1;
end
% Parameters
Ntrain = parm.Ntrain;

if Ntrain < 1, Info = []; return; end;

if isfield(parm,'Npre_train')
	Npre_train = parm.Npre_train;
else
%	Npre_train = Ntrain;
	if Tall >= 2*M*D
		Npre_train = 0;
	elseif Tall >= M*D
		Npre_train = fix(Ntrain/2);
	else
		Npre_train = Ntrain;
	end
end

if Npre_train > Ntrain, Npre_train = Ntrain; end;

if isfield(parm,'Nupdate')
	Nupdate = parm.Nupdate;
else
	Nupdate = 1;
end

fprintf('--- Output Dimension  = %d\n',N)
fprintf('--- Input  Dimension  = %d\n',M)
fprintf('--- Embedding  Dimension  = %d\n',D)
fprintf('--- Number of trials  = %d\n',Ntrial)
fprintf('--- Number of training sample = %d\n',Tall)
fprintf('--- Total update iteration    = %d (%d)\n',Ntrain,Npre_train)

% original input dimension
Xdim  = M;
M = Xdim*D;
M_ALL = M;

%
% --- Initialization
%

% Input/Output variance
sx = mean((X(:) - mean(X(:))).^2);
sy = mean((Y(:) - mean(Y(:))).^2);

SY0 = mean(sy);
A0  = 1./mean(sx);

if isfield(parm,'Ta0') && parm.Ta0 > 0,
	Ta0 = parm.Ta0;
	a0  = parm.a0 * A0;
else
	Ta0 = 0;
	a0  = 1;
end

% Input covariance
Trial = Trial+(D-1)*tau;

XX = zeros(Xdim,1);
for n=1:Ntrial
	XX = XX + sum(X(:,1:Trial(n), n).^2 , 2);
end
XX  = XX / sum(Trial);
%XX  = sum(sum(X.^2,3),2)/(Tx*Ntrial);
XX  = repmat(XX', [1 D]);% 1 x M

if isfield(Model,'ix_act')
	SY  = mean(Model.SY);  % 1 x 1

	% Active index
	ix_act = Model.ix_act;
	A = zeros(1,M_ALL);
	W = zeros(N,M_ALL);

	A(ix_act)   = sum(Model.A,1);
	W(:,ix_act) = Model.W;

	if M_ALL ~= Xdim*D,
		fprintf('M_ALL=%d,Xdim=%d,D=%d\n',M_ALL ,Xdim ,D)
		error('M_ALL ~= Xdim*D')
	end

	% Active index in input space without embedding
	IX_dim = find( sum(reshape(A,[Xdim,D]),2) > 0);

	IX_act = repmat( (0:(D-1))* Xdim ,[length(IX_dim) 1]) ...
	       + repmat(IX_dim, [1 D]);
	IX_act = IX_act(:);

	W  = W(:,IX_act) ;  % N x (M*D)
	A  = A(IX_act) ;  % 1 x (M*D)
	X  = X(IX_dim,:,:);
	XX = XX(IX_act);

	M     = length(IX_act);
	Xdim  = length(IX_dim);
else
	A = repmat(A0, [1,M_ALL]);
	W = zeros(N,M_ALL);
	SY  = SY0;
	% Save original input for pruning
	IX_act  = 1:M_ALL;
	IX_dim  = 1:Xdim;
end

ix_act  = 1:M;
ix_dim  = 1:Xdim;
M_all   = M;

% Delay embedding index for W
Wid = [(0:(D-1))'* Xdim + 1 , (1:D)'* Xdim];

% Working variable
G_A = zeros(N,M);       % N x M

if size(A,1)==Xdim && size(A,2)==1
	A   = repmat(A',[1 D]);
elseif size(A,1)==1 && size(A,2)==Xdim
	A   = repmat(A,[1 D]);
end

SW = SY./( Tall*XX + SY./A );

fprintf('a_min = %g\n', a_min)
fprintf('SY0 = %g\n', SY0)
fprintf('SY  = %g\n', SY)

% Free energy histry
FE  = zeros(Ntrain,1);
LP  = zeros(Ntrain,1);
H   = zeros(Ntrain,1);
Err = zeros(Ntrain,1);
Mhist = zeros(Ntrain,1);

% ARD hyper param. history
if isfield(parm,'Debug') && ~isempty(parm.Debug) && parm.Debug > 0
	Debug = 1;
	A_tmp = zeros(N*M_ALL, ceil(Ntrain/Nskip));
else
	Debug = 0;
end

% recover all component
A_all  = zeros(1,M_all);       % N x M

dY = error_delay_time_sw(X,Y,W,tau,Trial);
dY = dY .* trial_sw;                           % mask invalid samples

k_save  = 0;

%%%%%% Learning Loop %%%%%%
for k=1:Ntrain
	% Ainv = alpha , A = 1/alpha
	% (Y-W*X)^2/SY + W^2/A
	% ( (Y-W*X)^2 + W^2*Ainv )/SY
	Ainv    = SY./A;

    W   = weight_update_embed_sw(X, dY, W, Tall*XX, Ainv, tau, Trial);
	dY  = error_delay_time_sw(X, Y, W, tau, Trial);
	dY  = dY .* trial_sw;                           % mask invalid samples

    dYY = sum(dY(:).^2)/(N*Tall);
	WW  = sum(W.^2,1);

    % Noise variance update
    SY  = dYY + sum(WW .* Ainv)/(N*Tall);
    % Prevent zero variance
    SY  = max( SY, MINVAL);

    % Log variance
    SWA     = max( SW .* Ainv , MINVAL);
    log_sw  = N*(sum( log(SWA) - SWA + 1 ));
    log_sy  = N*( log(SY) );
    log_a   = Ta0*(sum(log(Ainv) - a0.*Ainv + 1));

    % Free energy
    LP(k)  = - (0.5*Tall) * log_sy ;
    H(k)   = 0.5*( log_sw + log_a - sum(WW .*Ainv) );
    FE(k)  = LP(k) + H(k);
    Err(k) = sum(dYY)/(N*SY0);

    % Weight variance

    SW = SY./( Tall*XX + Ainv );

    % Hyper parameter for weight variance (ARD)
	if mod(k,Nupdate) == 0,
	    % A = Alpha^-1 * SY
		% Ainv = SY./A;
	    % SW = SY./( Tall*XX + Ainv );

	    % G_A = 1 - SW./A;
	    %     = (Tall*XX + Ainv - SY/A) * SW/SY
	    G_A = Tall.*XX.*SW./SY;
	    G_A = max((G_A), MINVAL);

		% N*A = N * (Alpha * SY) =  (W.^2) + N * SW  ;
		if k <= Npre_train,
			% VB update rule (Stable)
			%  ARD for each weight
			A  = (WW + N*SW + 2*Ta0*a0)/( N + 2*Ta0 );
		else
			% Accelerated update rule (Unstable)
		    A  = sqrt( A.* WW./(G_A * N));
		    %A  = (WW + 2*Ta0*a0)./(G_A * N + 2*Ta0);
		end

		if space_ARD==1
			Am = mean(reshape(A,[M/D,D]),2);
			A  = repmat(Am', 1,D);
		end

	    % Prune small variance
	    if Prune == 1
		    % Find active input dimension
		    ix_act_old = ix_act;
		    ix_dim_old = ix_dim;

		    % recover all component
			A_all  = zeros(1,M_all);       % 1 x M
		    %  A_all(:,ix_act)  = A;
		    A_all(ix_act) = WW/max(WW);

		    % find active input dimension (absolute index)
		    ix_dim = find( sum(reshape(A_all,[Xdim,D]),2) > a_min );
		    ix_act = repmat(ix_dim, [1 D]) ...
		           + repmat([0:D-1]*Xdim, [length(ix_dim) 1]);
		    ix_act = ix_act(:);

		    Mnew   = length(ix_act);  		% # of effective input

		    if Mnew < M,
			    % convert to relative index
			    jx_act = trans_index(ix_act,ix_act_old,M_all);
			    jx_dim = trans_index(ix_dim,ix_dim_old,Xdim);

			    M   = Mnew;
			    A   = A(jx_act) ;  % N x M
			    W   = W(:,jx_act) ;  % N x M
			    SW  = SW(jx_act);  % N x M

			    X	 = X(jx_dim,:,:);  	 	% M x T
			    XX	 = XX(jx_act);  	 	% M x T
			end
	    end
	    % END of if Prune == 1

		A = max(A,MINVAL);

	end
	% END of if mod(k,Nupdate) == 0

	Mhist(k) = M;
	SW  = SW /SY;

    if mod(k, Nskip)==0
        % Save history
		if Debug == 1
        	k_save = k_save + 1;
        	A_tmp(:,k_save) = A_all(:);
		end

        fprintf('Iter = %4d, M = %4d, err = %g, F = %g, SY= %g, H = %g\n', ...
               k, length(ix_act), Err(k), FE(k), SY, - 2*H(k)/log(T));
    end

    % Convergence check
	if k > Ncheck,
		Fdif = (FE(k) - FE(k-Fstep))/(abs(FE(k))+eps);
	else
		Fdif = Fdiff + 1;
	end

	if (Fdiff > abs(Fdif)),
		fprintf('Converged : Free energy change = %g\n',Fdif)
		break;
	end;
end

ix_act = IX_act(ix_act);

% Active index
Model.ix_act = ix_act;
Model.M_all  = M_ALL ;

% Save output variable
Model.A    = A ;
Model.W    = W ;
Model.SY   = SY;
Model.SW   = SW; % = 1./(Tall*XX + diag(Ainv))

Model.method = 'linear_sparse_stepwise';
Model.mode   = 'scalar';
Model.sparse = 'sparse';

% Save history
Info.FE  = FE(1:k);
Info.LP  = LP(1:k);
Info.H   = H(1:k) ;
Info.Err = Err(1:k);
Info.M   = Mhist(1:k);

if exist('A_tmp','var')
	Info.A   = A_tmp(:,1:k_save) ;
end

% recover all component
%W_all   = zeros(N,M_all);
%SW_all  = zeros(N,M_all);
%
%A_all(:,ix_act)  = A;
%W_all(:,ix_act)  = W ;  % N x M
%SW_all(:,ix_act) = SW;  % N x M

%%% ---- Index transformation from old active_index to current active_index
function	jx = trans_index(ix,ix_old,M)

N = length(ix_old);
Itrans = zeros(M,1);
Itrans(ix_old) = 1:N;

jx = Itrans(ix);


function [ a, b ] = p11_lim ( dim_num )

%*****************************************************************************80
%
%% P11_LIM returns the integration limits for problem 11.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the argument.
%
%    Output, real A(DIM_NUM), B(DIM_NUM), the lower and upper
%    limits of integration.
%
  a(1:dim_num) = 0.0;
  b(1:dim_num) = 1.0;

  return
end


function gf = gradddivHexp(Hkt_r, varargin)
% function gf = gradddivH(Hkt_r, varargin)
% gf is 1 x k*t row vector
% Hkt_r = reshape(Hkt,1,k*t) -> row vector
% Vxt = varargin{1};  %data
% Wxk = varargin{2};  %W matrix
% Wxk_fix = varargin{3}; %fixed part of the Wxk matrix (e.g. background) ->rows
% Hkt_fix = varargin{4}; %fixed part (lines) of the H matrix (e.g. background)

alphaH=1; %for now....
Vxt = varargin{1};  %data
Wxk_tmp = varargin{2};  %W matrix
Wxk_fix = varargin{3}; %fixed part of the Wxk matrix (e.g. background) ->rows
Hkt_fix = varargin{4}; %fixed part (lines) of the H matrix (e.g. background)
peval = varargin{5}; %parameters

if ~isfield(peval, 'w_lambda') peval.w_lambda=0; end

t=size(Vxt,2);
k=length(peval.h_dovec);

Hkt_tmp = exp(reshape(Hkt_r,k,t));

Wxk = zeros(peval.numpix, peval.ncomp+1);
Hkt = zeros(peval.ncomp+1, peval.nt);

Wxk(:,peval.w_dovec)=Wxk_tmp;
Hkt(peval.h_dovec,:)=Hkt_tmp;

Wxk(:,peval.w_fixvec)=Wxk_fix;
Hkt(peval.h_fixvec,:)=Hkt_fix;

deltasum=sum(sum(Wxk_tmp,1))-k;
if and(~isempty(Wxk_tmp), abs(deltasum)>10^-6)
    error('Wxk is not correctly normalized! (sum(Wxk_tmp,1)<>1)\n sum(Wxk_tmp,1)=%f',deltasum)
end

ap = peval.alphapen;
sumH_t = sum(Hkt,2);
sumH_t_sq = sum(sumH_t.^ap);
sumH = sum(sumH_t);

penaltyterm = (1-ap)*(1/(sumH)^ap)*sum(sumH_t_sq) + ap*(1/sumH^(ap-1))*(sumH_t).^(ap-1);
penaltyterm_kt = repmat(penaltyterm, 1, t);

gfkt = (1-Wxk'*(Vxt./(Wxk*Hkt)))*alphaH.*Hkt + penaltyterm_kt; %d/dh(d-divergence)
% one is tehre because Wxt is normalized: sum(Wxt,1)=1
gf=reshape(gfkt(1:k,:),1,k*t); %making row vector


% area of ellipse
function [data,units] = compute_area(trx,n)

flies = trx.exp2flies{n};
nflies = numel(flies);
data = cell(1,nflies);
for i = 1:nflies,
  fly = flies(i);
  data{i} = (2*trx(fly).a_mm).*(2*trx(fly).b_mm)*pi;
end
units = parseunits('mm^2');


clc; clear all; close all;
I = checkerboard(50,3,3);
h = fspecial('gaussian',[5 5],2);
harris(I,0.05,0.01,h);

github-repos/MATLAB/decouples-Matlab_deep_learning/Matlab_deep_learning-1b823b82686080e32b03e1f1a4648896bd6e3c44/第 17 章 基于 Harris 的角点特征检测/main.m


function [ a, b ] = p04_lim ( dim_num )

%*****************************************************************************80
%
%% P04_LIM returns the integration limits for problem 04.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the argument.
%
%    Output, real A(DIM_NUM), B(DIM_NUM), the lower and upper
%    limits of integration.
%
  a(1:dim_num) = 0.0;
  b(1:dim_num) = 1.0;

  return
end


function MountainCarPlot( x,a,steps )
subplot(2,1,2);

xplot =-1.6:0.05:0.6;
yplot =sin(3*xplot);
%Mountain
h = area(xplot,yplot,-1.1);
set(h,'FaceColor',[.1 .7 .1])
hold on
% Car  [1 .7 .1]
plot(x(1),sin(3*x(1))+0.1,'ok','markersize',12,'MarkerFaceColor',[1 .7 .1]);
%Goal
plot(0.45,sin(3*0.5)+0.1,'-pk','markersize',15,'MarkerFaceColor',[1 .7 .1]);
% direction of the force
if (a<0)
      plot(x(1)-0.08,sin(3*x(1))+0.1,'<k','MarkerFaceColor','g','markersize',10);
elseif (a>0)
      plot(x(1)+0.08,sin(3*x(1))+0.1,'>k','MarkerFaceColor','g','markersize',10);
end

title(strcat ('Step: ',int2str(steps)));
%-----------------------
axis([-1.6 0.6 -1.1 1.5]);
drawnow
hold off


function db=lpcar2db(ar,np)
%LPCAR2DB LPC: Convert AR coefs to power spectrum in dB DB=(AR)

%      Copyright (C) Mike Brookes 1998
%      Version: $Id: lpcar2db.m,v 1.4 2007/05/04 07:01:38 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[nf,p1]=size(ar);
if nargin<2 np=p1-1; end
ff=rfft(ar.',2*np+2).';
db=-10*log10(real(ff.*conj(ff)));
if nargout==0
   plot((0:np+1)/(2*np+2),db.');
   ylabel('dB');
end


%
% Type-level resampling using MCMC
%
% Sample a chain using ps.mcmc.nsamp_type_chain iterations
%
% Store a subset (ps.mcmc.nsamp_type_store) of these samples linearly
% spaced along the chain
%
% Return
%   samples_store: [nsamp_store x 1 cell]
%
function samples_store = RunMCMCType(M,lib)

    ps = defaultps;

    % fill-in type-level shape variables
    Q = M.copy();
    if isempty(Q.S{1}.shapes_type)
       for sid=1:M.ns
          Q.S{sid}.shapes_type = Q.S{sid}.shapes_token;
       end
    end

    % fill-in type-level eval variable
    ns = Q.ns;
    for sid=1:ns
       R = Q.S{sid}.R;
       if strcmp(R.type,'mid') && isempty(Q.S{sid}.R.eval_spot_type)
           Q.S{sid}.R.eval_spot_type = Q.S{sid}.R.eval_spot_token;
       end
    end

    % run mcmc
    samples_chain = mcmc_all(Q,lib,ps.mcmc.nsamp_type_chain,'type');

    % pick well-spaced set
    int = ps.mcmc.nsamp_type_chain ./ ps.mcmc.nsamp_type_store;
    indx = round(linspace(int,ps.mcmc.nsamp_type_chain,ps.mcmc.nsamp_type_store));
    samples_store = samples_chain(indx);

end


function res = transformLine3d(line, trans)
%TRANSFORMLINE3D Transform a 3D line with a 3D affine transform.
%
%   LINE2 = transformLine3d(LINE1, TRANS)
%
%   Example
%   P1 = [10 20 30];
%   P2 = [30 40 50];
%   L = createLine3d(P1, P2);
%   T = createRotationOx(P1, pi/6);
%   L2 = transformLine3d(L, T);
%   figure; hold on;
%   axis([0 100 0 100 0 100]); view(3);
%   drawPoint3d([P1;P2]);
%   drawLine3d(L, 'b');
%   drawLine3d(L2, 'm');
%
%   See also:
%   lines3d, transforms3d, transformPoint3d, transformVector3d
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2008-11-25,    using Matlab 7.7.0.471 (R2008b)
% Copyright 2008 INRA - BIA PV Nantes - MIAJ Jouy-en-Josas.

res = [...
    transformPoint3d(line(:, 1:3), trans) ...   % transform origin point
    transformVector3d(line(:,4:6), trans)];     % transform direction vect.


% sph2topo() - Convert from a 3-column headplot file in spherical coordinates
%              to 3-column topoplot() locs file in polar (not cylindrical) coords.
%              Used for topoplot() and other 2-D topographic plotting programs.
%              Assumes a spherical coordinate system in which horizontal angles
%              have a range [-180,180] deg,  with zero pointing to the right ear.
%              In the output polar coordinate system, zero points to the nose.
%              See  >> help readlocs
% Usage:
%          >> [chan_num,angle,radius] = sph2topo(input,shrink_factor,method);
%
% Inputs:
%   input         = [channo,az,horiz] = chan_number, azumith (deg), horiz. angle (deg)
%                   When az>0, horiz=0 -> right ear, 90 -> nose
%                   When az<0, horiz=0 -> left ear, -90 -> nose
%   shrink_factor = arc_length shrinking factor>=1 (deprecated).
%                   1 -> plot edge is 90 deg azimuth {default};
%                   1.5 -> plot edge is +/-135 deg azimuth See
%                   >> help topoplot().
%   method        = [1|2], optional. 1 is for Besa compatibility, 2 is for
%                   compatibility with Matlab function cart2sph(). Default is 2
%
% Outputs:
%   channo  = channel number (as in input)
%   angle   = horizontal angle (0 -> nose; 90 -> right ear; -90 -> left ear)
%   radius  = arc_lengrh from vertex (Note: 90 deg az -> 0.5/shrink_factor);
%             By topoplot() convention, radius=0.5 is the nasion-ear_canal plane.
%             Use topoplot() 'plotrad' to plot chans with abs(az) > 90 deg.
%
% Author: Scott Makeig & Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 6/12/98
%
% See also: cart2topo(), topo2sph()

% Copyright (C) 6/12/98 Scott Makeig, SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% corrected left/right orientation mismatch, Blair Hicks 6/20/98
% changed name sph2pol() -> sph2topo() for compatibility -sm
% 01-25-02 reformated help & license -ad
% 01-25-02 changed computation so that it works with sph2topo -ad

function [channo,angle,radius] = sph2topo(input,factor, method)

chans = size(input,1);
angle = zeros(chans,1);
radius = zeros(chans,1);

if nargin < 1
   help sph2topo
   return
end

if nargin< 2
  factor = 0;
end
if factor==0
  factor = 1;
end
if factor < 1
  help sph2topo
  return
end

if size(input,2) ~= 3
   help sph2topo
   return
end

channo = input(:,1);
az = input(:,2);
horiz = input(:,3);

if exist('method')== 1 & method == 1
  radius = abs(az/180)/factor;
  i = find(az>=0);
  angle(i) = 90-horiz(i);
  i = find(az<0);
  angle(i) = -90-horiz(i);
else
  angle  = -horiz;
  radius = 0.5 - az/180;
end;


classdef IMODE < ALGORITHM
% <single> <real/integer> <large/none> <constrained/none>
% Improved multi-operator differential evolution
% minN  ---   4 --- Minimum population size
% aRate --- 2.6 --- Ratio of archive size to population size

%------------------------------- Reference --------------------------------
% K. M. Sallam, S. M. Elsayed, R. K. Chakrabortty, and M. J. Ryan, Improved
% multi-operator differential evolution algorithm for solving unconstrained
% problems, Proceedings of the IEEE Congress on Evolutionary Computation,
% 2020.
%------------------------------- 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".
%--------------------------------------------------------------------------

    methods
        function main(Algorithm,Problem)
            %% Parameter setting
            [minN,aRate] = Algorithm.ParameterSet(4,2.6);

            %% Generate random population
            Population = Problem.Initialization();
            Archive    = [];
            MCR = zeros(20*Problem.D,1) + 0.2;
            MF  = zeros(20*Problem.D,1) + 0.2;
            k   = 1;
            MOP = ones(1,3)/3;

            %% Optimization
            while Algorithm.NotTerminated(Population)
                % Reduce the population size
                N          = ceil((minN-Problem.N)*Problem.FE/Problem.maxFE) + Problem.N;
                [~,rank]   = sort(FitnessSingle(Population));
                Population = Population(rank(1:N));
                Archive    = Archive(randperm(end,min(end,ceil(aRate*N))));
                % Generate parents, CR, F, and operator for each offspring
                Xp1 = Population(ceil(rand(1,N).*max(1,0.25*N))).decs;
                Xp2 = Population(ceil(rand(1,N).*max(2,0.5*N))).decs;
                Xr1 = Population(randi(end,1,N)).decs;
                Xr3 = Population(randi(end,1,N)).decs;
                P   = [Population,Archive];
                Xr2 = P(randi(end,1,N)).decs;
                CR  = randn(N,1).*sqrt(0.1) + MCR(randi(end,N,1));
                CR  = sort(CR);
                CR  = repmat(max(0,min(1,CR)),1,Problem.D);
                F   = min(1,trnd(1,N,1).*sqrt(0.1) + MF(randi(end,N,1)));
                while any(F<=0)
                    F(F<=0) = min(1,trnd(1,sum(F<=0),1).*sqrt(0.1) + MF(randi(end,sum(F<=0),1)));
                end
                F  = repmat(F,1,Problem.D);
                OP = arrayfun(@(S)find(rand<=cumsum(MOP),1),1:N);
                OP = arrayfun(@(S)find(OP==S),1:length(MOP),'UniformOutput',false);
                % Generate offspring
                PopDec = Population.decs;
                OffDec = PopDec;
                OffDec(OP{1},:) = PopDec(OP{1},:) + F(OP{1},:).*(Xp1(OP{1},:)-PopDec(OP{1},:)+Xr1(OP{1},:)-Xr2(OP{1},:));
                OffDec(OP{2},:) = PopDec(OP{2},:) + F(OP{2},:).*(Xp1(OP{2},:)-PopDec(OP{2},:)+Xr1(OP{2},:)-Xr3(OP{2},:));
                OffDec(OP{3},:) = F(OP{3},:).*(Xr1(OP{3},:)+Xp2(OP{3},:)-Xr3(OP{3},:));
                if rand < 0.4
                    Site = rand(size(CR)) > CR;
                    OffDec(Site) = PopDec(Site);
                else
                    p1 = randi(Problem.D,N,1);
                    p2 = arrayfun(@(S)find([rand(1,Problem.D),2]>CR(S,1),1),1:N);
                    for i = 1 : N
                        Site = [1:p1(i)-1,p1(i)+p2(i):Problem.D];
                        OffDec(i,Site) = PopDec(i,Site);
                    end
                end
                Offspring = Problem.Evaluation(OffDec);
                % Update the population and archive
                delta   = FitnessSingle(Population) - FitnessSingle(Offspring);
                replace = delta > 0;
                Archive = [Archive,Population(replace)];
                Archive = Archive(randperm(end,min(end,ceil(aRate*N))));
                Population(replace) = Offspring(replace);
                % Update CR, F, and probabilities of operators
                if any(replace)
                    w      = delta(replace)./sum(delta(replace));
                    MCR(k) = (w'*CR(replace,1).^2)./(w'*CR(replace,1));
                    MF(k)  = (w'*F(replace,1).^2)./(w'*F(replace,1));
                    k      = mod(k,length(MCR)) + 1;
                else
                    MCR(k) = 0.5;
                    MF(k)  = 0.5;
                end
                delta = max(0,delta./abs(FitnessSingle(Population)));
                if any(cellfun(@isempty,OP))
                	MOP = ones(1,3)/3;
                else
                    MOP = cellfun(@(S)mean(delta(S)),OP);
                    MOP = max(0.1,min(0.9,MOP./sum(MOP)));
                end
            end
        end
    end
end


function weig = get_w(supVec,method)
%
%                w = get_w()
%
% Returns value of w from svm
%
% AE: i have changed this procedure to include non linear feature
% selection with RFE. When non-linear, it gives  a score vector for each
% feature (used in RFE) which is not the margin but is sorted as the margin

kerTemp = sv.child.kerparam;
if strcmp(sv.child.ker,'linear')
  weig=sv.alpha'*get_x(sv.Xsv);
  return;
end

if strcmp(sv.child.ker,'weighted_linear')
  numEx=get_dim(sv.Xsv);
  weig=sv.alpha'* (get_x(sv.Xsv) .*  repmat(kerTemp,numEx,1));
  return;
end
if strcmp(sv.child.ker,'rbf')  | strcmp(sv.child.ker,'poly'),
    xTemp = get_x(sv.Xsv);
    alphaTemp = sv.alpha;

    if strcmp(sv.child.ker,'rbf'),

      % compute the kernel matrix for all components
      K = xTemp*xTemp';
      Kdn = sum(xTemp.^2,2);
      Kn = sum(xTemp.^2,2);
      K = ones(size(xTemp,1),1)*Kdn' + Kn*ones(1,size(xTemp,1)) - 2*K;
      K = exp(-K/(2*kerTemp));
      % compute the margin when one component is removed
       for i = 1:size(xTemp,2),
           Ki = xTemp(:,i)*ones(1,size(xTemp,1)) - ones(size(xTemp,1),1)*xTemp(:,i)';
           Ki = Ki.^2;
           Ki = Ki/(2*kerTemp);
           Ki = exp(Ki);
           weig(i) = (alphaTemp'*(K.*Ki)*alphaTemp);
       end;
    elseif strcmp(sv.child.ker,'poly'),
        % compute the margin when one component is removed
        Ktmp = xTemp*xTemp';
        for i = 1:size(xTemp,2),
           Ki = xTemp(:,i)*xTemp(:,i)';
           K_i = (Ktmp - Ki+1).^(kerTemp);
           weig(i) = (alphaTemp'*K_i*alphaTemp);
    	end;
    end;% if strcmp(...,'rbf')
    weig=max(weig)-weig;  %% make largest the smallest --- wrong way round!
    return;
end;% if strcmp(... | strcmp(...,'poly')
%%% if this point is reached then the kernel is a non classic one
ker=supVec.child.ker;
if strcmp(ker,'custom'),
    error('Get w not implemented for CUSTOM kernels.');
    return;
end;
%%% if tpoly kernel -> used for nfe
if strcmp(ker,'tpoly'),
    [numEx,vDim,oDim]=get_dim(supVec.Xsv);
    xTemp = get_x(supVec.Xsv);
    alphaTemp = supVec.alpha;
    weig = ones(length(supVec.child.param,vDim));

    for j=1:length(supVec.child.kerparam),
        ktmp = supVec.child;
        kerp = ktmp.kerparam;
        for i = 1:length(kerp{j}),
            kerptmp=kerp;
            kerptmp{j} = [kerp{j}(1:i-1),kerp{j}(i+1:length(kerp{j}))];
            ktmp.kerparam=kerptmp;
            K_i = get_kernel(ktmp,supVec.Xsv,supVec.Xsv);
            weig(j,kerp{j}(i)) = (alphaTemp'*K_i*alphaTemp);
        end;
    end;
    weig = max(max(weig))-weig;
    return;
end;
for i = 1:size(xTemp,2),
    dtmp = data('tmp',[xTemp(:,1:(i-1)),xTemp(:,(i+1):size(xTemp,2))],[]);
    Ki = get_kernel(supVec.child,dtmp,dtmp);
    weig(i) = (alphaTemp'*Ki*alphaTemp);
end;
weig=max(weig)-weig;


function z = power( x, y )

%   Disciplined convex programming information for POWER (.^):
%      When used in CVX expressions, either X or Y must be constant. Only
%      certain convex or concave branches are accepted as valid:
%         --- if both X and Y are constant, then Z = X.^Y is interpreted
%             precisely as the MATLAB built-in version.
%         --- if Y is constant and 0 < Y < 1, then Z = X.^Y is concave and
%             nondecreasing in X. Therefore, X must be concave, and is
%             implicitly constrained to be nonnegative.
%         --- if Y is constant and Y == 1, then Z = X.
%         --- if Y is constant and a positive even integer, then Z = X.^Y
%             is convex and nonmonotonic in X. Therefore, X must be affine.
%         --- if Y is constant and Y > 1, but *not* an integer, then
%             Z = X.^Y is convex and nonmonotonic in X. Therefore, X must
%             be affine (and real), and is implicitly constrained to be
%             nonnegative.
%      In expert mode, additional cases are handled:
%         --- if X is constant and 0 < X < 1, then Z = X.^Y is convex and
%             nonincreasing in X. Therefore, Y must be concave.
%         --- if X is constant and X == 1, then Z = 1.
%         --- if X is constant and X > 1, then Z = X.^Y is convex and
%             nondecreasing in X. Therefore, Y must be convex.
%      All other combinations are rejected as invalid. For instance, if Y
%      is an odd integer, then X .^ Y is neither convex nor concave, so it
%      is rejected. In such cases, consider using POW_P, POW_POS, or
%      POW_ABS instead.
%
%   Disciplined geometric programming information for POWER (.^):
%      In disciplined geometric programs, the power operation Z=X.^Y is
%      valid only if Y is a real constant. There are no restrictions on
%      X. Note that a negative exponent Y reverses curvature; that is, Z
%      is log-convex if X is log-concave, and vice versa.

%
% Check sizes
%

sx = size( x ); xs = all( sx == 1 );
sy = size( y ); ys = all( sy == 1 );
if xs,
    sz = sy;
elseif ys || isequal( sx, sy ),
    sz = sx;
else
    error( 'Matrix dimensions must agree.' );
end

%
% Determine the expression types
%

if cvx_isconstant( y ),

    z = pow_cvx( x, y, 'power' );
    return

elseif ~cvx_isconstant( x ),

    error( 'Disciplined convex programming error:\n   In an expression X .^ Y, either X or Y must be constant.', 1 ); %#ok

end

%
% Now handle constant .^ non-constant
%

persistent remap
if isempty( remap ),
	remap_y1 = cvx_remap( 'real-affine' );
	remap_y2 = cvx_remap( 'convex' )    & ~remap_y1;
	remap_y3 = cvx_remap( 'concave' )   & ~remap_y1;
	remap_y4 = cvx_remap( 'log-valid' ) & ~( remap_y1 | remap_y2 | remap_y3 );
	remap    = [0;0;2;2;2] * remap_y1 + ...
	           [0;0;0;2;2] * remap_y2 + ...
	           [0;0;2;2;0] * remap_y3 + ...
	           [0;1;0;2;0] * remap_y4;
end
x  = cvx_constant( x );
vy = cvx_classify( y );
vx = 1 + isreal( x ) .* ( ( x >= 0 ) + ( x > 0 ) + ( x >= 1 ) + ( x > 1 ) );
vr = remap( vx + size( remap, 1 ) * ( vy - 1 ) );
vu = sort( vr(:) );
vu = vu([true;diff(vu)~=0]);
nv = length( vu );

%
% Perform the individual computations and combine
%

x = cvx( x ); xt = x;
y = cvx( y ); yt = y;
if nv ~= 1,
    z = cvx( sz, [] );
end
for k = 1 : nv,

    %
    % Select the category of expression to compute
    %

    if nv ~= 1,
        t = vr == vu( k );
        if ~xs, xt = cvx_subsref( x, t ); sz = size( xt ); end
        if ~ys, yt = cvx_subsref( y, t ); sz = size( yt ); end
    end

    %
    % The computational kernels
    %

    switch vu( k ),
        case 0,
            % Invalid
            error( 'Disciplined convex programming error:\n    Cannot perform the operation {%s}.^{%s}', cvx_class( xt, true, true, true ), cvx_class( yt, true, true, true ) );
        case 1,
            % zero .^ convex
            cvx_optval = cvx( zeros( sz ) );
        case 2,
            % (0<x<1) .^ concave, (x>1) .^ convex
            cvx_optval = exp( log( cvx_constant( xt ) ) .* yt );
        otherwise,
            error( 'Shouldn''t be here.' );
    end

    %
    % Store the results
    %

    if nv == 1,
        z = cvx_optval;
    else
        z = cvx_subsasgn( z, t, cvx_optval );
    end

end

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


clear all; close all; clc;

S = spherefactory(5, 2);
M = powermanifold(S, 7);
checkmanifold(M);
checkretraction(M);


function y = modu(x,dzdy)
%ModU activation function
%Ye, C., Yang, Y., Fermuller, C., & Aloimonos, Y. (2017).
%On the Importance of Consistency in Training Deep Neural Networks. arXiv preprint arXiv:1708.00631.

  if nargin <= 1 || isempty(dzdy)
    y = abs(x) ;
  else
    y = dzdy .* sign(x) ;
  end

end


%% Importing Crystal Orientations
%
%%
% In order to import orientation data from a text file we first need to
% defined the corresponding <CrystalSymmetries.html crystal symmetry>, e.g.
% by a cif file

cs = crystalSymmetry.load('quartz.cif')

%%
% In the second step we may use the command <orientation.load.html
% |orientation.load|> to load the data. This function requires that one
% specifies the meaning of the column of the import file by the option
% |columnNames|.

fname = fullfile(mtexDataPath,'orientation','Tongue_Quartzite_Bunge_Euler');
ori = orientation.load(fname,'columnNames',{'phi1','Phi','phi2'},cs)

%%
% This creates a variable of type @orientation which can be used for
% further analysis, e.g. to plot pole figures

plotPDF(ori,Miller({0,0,0,1},{1,0,-1,0},cs))


function test_tutorial_multivariateanalysis(datadir, dmltdir)

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_timelockstatistics ft_topoplotER ft_freqstatistics ft_topoplotTFR

% this is a test script that I made following the report of Matt on
% http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=1585 and realizing that the
% wiki page http://www.fieldtriptoolbox.org/tutorial/multivariateanalysis was
% not included in a test script.

% This test script corresponds to the documentation on the wiki from 3 July 2012

if nargin==0
  datadir = dccnpath('/home/common/matlab/fieldtrip/data/ftp/tutorial/classification');
  dmltdir = dccnpath('/home/common/matlab/fieldtrip/external/dmlt');
end

addpath(genpath(dmltdir));

filename = dccnpath(fullfile(datadir, 'covatt'));
load(filename);

cfg             = [];
cfg.parameter   = 'trial';
cfg.keeptrials  = 'yes'; % classifiers operate on individual trials
cfg.channel     = {'MLO' 'MRO'}; % occipital channels only

tleft   = ft_timelockanalysis(cfg,left);
tright  = ft_timelockanalysis(cfg,right);

cfg         = [];
cfg.layout  = 'CTF275.lay';
cfg.method  = 'crossvalidate';

cfg.design  = [ones(size(tleft.trial,1),1); 2*ones(size(tright.trial,1),1)]';
cfg.latency = [2.0 2.5]; % final bit of the attention period
stat = ft_timelockstatistics(cfg,tleft,tright);

disp(stat.statistic)

% this is the part that Matt mentioned in bug 1585
cfg.statistic = {'accuracy' 'binomial' 'contingency'};

stat = ft_timelockstatistics(cfg,tleft,tright);

disp(stat.statistic.contingency)

stat.mymodel = stat.model{1}.primal;

cfg              = [];
cfg.parameter    = 'mymodel';
cfg.layout       = 'CTF275.lay';
cfg.xlim         = [2.0 2.5];
cfg.comments     = '';
cfg.colorbar     = 'yes';
cfg.interplimits = 'electrodes';
ft_topoplotER(cfg,stat);

cfg              = [];
cfg.output       = 'pow';
cfg.method       = 'mtmconvol';
cfg.taper        = 'hanning';
cfg.foi          = 8:2:14;
cfg.t_ftimwin    = ones(length(cfg.foi),1).*0.5;
cfg.channel      = {'MLO' 'MRO'};
cfg.toi          = 2.0:0.1:2.5;
cfg.keeptrials   = 'yes'; % classifiers operate on individual trials

tfrleft          = ft_freqanalysis(cfg, left);
tfrright         = ft_freqanalysis(cfg, right);

cfg         = [];
cfg.layout  = 'CTF275.lay';
cfg.method  = 'crossvalidate';
cfg.design  = [ones(size(tfrleft.powspctrm,1),1); 2*ones(size(tfrright.powspctrm,1),1)]';
stat        = ft_freqstatistics(cfg,tfrleft,tfrright);

disp(stat.statistic)

stat.mymodel = stat.model{1}.primal;

cfg              = [];
cfg.layout       = 'CTF275.lay';
cfg.parameter    = 'mymodel';
cfg.comment      = '';
cfg.colorbar     = 'yes';
cfg.interplimits = 'electrodes';
ft_topoplotTFR(cfg,stat);

cfg         = [];
cfg.layout  = 'CTF275.lay';
cfg.method  = 'crossvalidate';
cfg.design  = [ones(size(tfrleft.powspctrm,1),1); 2*ones(size(tfrright.powspctrm,1),1)]';
cfg.mva     = {dml.standardizer dml.enet('family','binomial','alpha',0.2)};

stat = ft_freqstatistics(cfg,tfrleft,tfrright);

disp(stat.statistic)

stat.mymodel     = stat.model{1}.weights;

cfg              = [];
cfg.layout       = 'CTF275.lay';
cfg.parameter    = 'mymodel';
cfg.comment      = '';
cfg.colorbar     = 'yes';
cfg.interplimits = 'electrodes';
ft_topoplotTFR(cfg,stat);


function shmDataSimulated(x0, springConstant, noiseFactor, outFileName)
% Generate simulated pendulum data

%   Copyright 2008-2009 The MathWorks, Inc.
%   $Revision: 35 $    $Date: 2009-05-29 15:27:34 +0100 (Fri, 29 May 2009) $

if nargin<4
    outFileName = 'shmData.xls';
end

mass = 1;  % kg

% Determine the natural frequency of the pendulum
omega0 = sqrt(springConstant/mass);

% Simulate the pendulum motion
res = shmSimulation(x0,springConstant,mass);

% Add noise to position and velocity
positionNoise = randn(size(res.Position))*noiseFactor*x0;
velocityNoise = randn(size(res.Position))*noiseFactor*x0*omega0;

% Include this noise into the position and velocity
res.Position = res.Position + positionNoise;
res.Velocity = res.Velocity + velocityNoise;

% Format the data for writing to the Excel spreadsheet.
colHeadings = {'Time', 'Position', 'Velocity'};
dataArray = [res.Time res.Position res.Velocity];

% Create the cell array to write to the Excel file by combining the column
% headings and the numeric simulation results.  To do this we need to
% convert the array of numeric data to a cell array using num2cell.  Use
% cell2mat to convert a cell array of numbers back to a matrix.
dataArray = [colHeadings; num2cell(dataArray)];
% Save the data
xlswrite(outFileName,dataArray);


% -------------------------------------------------------------------------------------------------------------------------
function [init_sz, final_sz] = ideal_size(net, max_sz)
%   Luca Bertinetto, Jack Valmadre, Joao F. Henriques, 2016
% -------------------------------------------------------------------------------------------------------------------------
final_sz = forward(net, max_sz);
init_sz = backward(net, final_sz);
while ~all(init_sz <= max_sz)
    final_sz = final_sz - 1;
    init_sz = backward(net, final_sz);
end

end

function n = forward(net, n)
    for i = 1:numel(net.layers)
        l = net.layers{i};
        switch l.type
        case 'conv'
            m = [size(l.weights{1}, 1), size(l.weights{1}, 2)];
            n = filter(n, l.pad, m, l.stride);
        case 'pool'
            n = filter(n, l.pad, l.pool, l.stride);
        end
    end
end

function n = backward(net, n)
    for i = numel(net.layers):-1:1
        l = net.layers{i};
        switch l.type
        case 'conv'
            m = [size(l.weights{1}, 1), size(l.weights{1}, 2)];
            n = unfilter(n, l.pad, m, l.stride);
        case 'pool'
            n = unfilter(n, l.pad, l.pool, l.stride);
        end
    end
end

function n = filter(n, pad, m, k)
assert(numel(pad) == 1);
n = floor((n + 2*pad - m) / k) + 1;
end

function n = unfilter(n, pad, m, k)
assert(numel(pad) == 1);
n = k*(n - 1) + m - 2*pad;
end


function [H,Ip] = imagesAlign( I, Iref, varargin )
% Fast and robust estimation of homography relating two images.
%
% The algorithm for image alignment is a simple but effective variant of
% the inverse compositional algorithm. For a thorough overview, see:
%   "Lucas-kanade 20 years on A unifying framework,"
%   S. Baker and I. Matthews. IJCV 2004.
% The implementation is optimized and can easily run at 20-30 fps.
%
% type may take on the following values:
%  'translation'  - translation only
%  'rigid'        - translation and rotation
%  'similarity'   - translation, rotation and scale
%  'affine'       - 6 parameter affine transform
%  'rotation'     - pure rotation (about x, y and z)
%  'projective'   - full 8 parameter homography
% Alternatively, type may be a vector of ids between 1 and 8, specifying
% exactly the types of transforms allowed. The ids correspond, to: 1:
% translate-x, 2: translate-y, 3: uniform scale, 4: shear, 5: non-uniform
% scale, 6: rotate-z, 7: rotate-x, 8: rotate-y. For example, to specify
% translation use type=[1,2]. If the transforms don't form a group, the
% returned homography may have more degrees of freedom than expected.
%
% Parameters (in rough order of importance): [resample] controls image
% downsampling prior to computing H. Runtime is proportional to area, so
% using resample<1 can dramatically speed up alignment, and in general not
% degrade performance much. [sig] controls image smoothing, sig=2 gives
% good performance, setting sig too low causes loss of information and too
% high will violate the linearity assumption. [epsilon] defines the
% stopping criteria, use to adjust performance versus speed tradeoff.
% [lambda] is a regularization term that causes small transforms to be
% favored, in general any small non-zero setting of lambda works well.
% [outThr] is a threshold beyond which pixels are considered outliers, be
% careful not to set too low. [minArea] determines coarsest scale beyond
% which the image is not downsampled (should not be set too low). [H0] can
% be used to specify an initial alignment. Use [show] to display results.
%
% USAGE
%  [H,Ip] = imagesAlign( I, Iref, varargin )
%
% INPUTS
%  I          - transformed version of I
%  Iref       - reference grayscale double image
%  varargin   - additional params (struct or name/value pairs)
%   .type       - ['projective'] see above for options
%   .resample   - [1] image resampling prior to homography estimation
%   .sig        - [2] amount of Gaussian spatial smoothing to apply
%   .epsilon    - [1e-3] stopping criteria (min change in error)
%   .lambda     - [1e-6] regularization term favoring small transforms
%   .outThr     - [inf] outlier threshold
%   .minArea    - [4096] minimum image area in coarse to fine search
%   .H0         - [eye(3)] optional initial homography estimate
%   .show       - [0] optionally display results in figure show
%
% OUTPUTS
%  H        - estimated homography to transform I into Iref
%  Ip       - tranformed version of I (slow to compute)
%
% EXAMPLE
%  Iref = double(imread('cameraman.tif'))/255;
%  H0 = [eye(2)+randn(2)*.1 randn(2,1)*10; randn(1,2)*1e-3 1];
%  I = imtransform2(Iref,H0^-1,'pad','replicate');
%  o=50; P=ones(o)*1; I(150:149+o,150:149+o)=P;
%  prmAlign={'outThr',.1,'resample',.5,'type',1:8,'show'};
%  [H,Ip]=imagesAlign(I,Iref,prmAlign{:},1);
%  tic, for i=1:30, H=imagesAlign(I,Iref,prmAlign{:},0); end;
%  t=toc; fprintf('average fps: %f\n',30/t)
%
% See also imTransform2
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.61
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

% get parameters
dfs={'type','projective','resample',1,'sig',2,'epsilon',1e-3,...
  'lambda',1e-6,'outThr',inf,'minArea',4096,'H0',eye(3),'show',0};
[type,resample,sig,epsilon,lambda,outThr,minArea,H0,show] = ...
  getPrmDflt(varargin,dfs,1);
filt = filterGauss(2*ceil(sig*2.5)+1,[],sig^2);

% determine type of transformation to recover
if(isnumeric(type)), assert(length(type)<=8); else
  id=find(strcmpi(type,{'translation','rigid','similarity','affine',...
    'rotation','projective'})); msgId='piotr:imagesAlign';
  if(isempty(id)), error(msgId,'unknown type: %s',type); end
  type={1:2,[1:2 6],[1:3 6],1:6,6:8,1:8}; type=type{id};
end; keep=zeros(1,8); keep(type)=1; keep=keep>0;

% compute image alignment (optionally resample first)
prm={keep,filt,epsilon,H0,minArea,outThr,lambda};
if( resample==1 ), H=imagesAlign1(I,Iref,prm); else
  S=eye(3); S([1 5])=resample; H0=S*H0*S^-1; prm{4}=H0;
  I1=imResample(I,resample); Iref1=imResample(Iref,resample);
  H=imagesAlign1(I1,Iref1,prm); H=S^-1*H*S;
end

% optionally rectify I and display results (can be expensive)
if(nargout==1 && show==0), return; end
Ip = imtransform2(I,H,'pad','replicate');
if(show), figure(show); clf; s=@(i) subplot(2,3,i);
  Is=[I Iref Ip]; ri=[min(Is(:)) max(Is(:))];
  D0=abs(I-Iref); D1=abs(Ip-Iref); Ds=[D0 D1]; di=[min(Ds(:)) max(Ds(:))];
  s(1); im(I,ri,0); s(2); im(Iref,ri,0); s(3); im(D0,di,0);
  s(4); im(Ip,ri,0); s(5); im(Iref,ri,0); s(6); im(D1,di,0);
  s(3); title('|I-Iref|'); s(6); title('|Ip-Iref|');
end

end

function H = imagesAlign1( I, Iref, prm )

% apply recursively if image large
[keep,filt,epsilon,H0,minArea,outThr,lambda]=deal(prm{:});
[h,w]=size(I); hc=mod(h,2); wc=mod(w,2);
if( w*h<minArea ), H=H0; else
  I1=imResample(I(1:(h-hc),1:(w-wc)),.5);
  Iref1=imResample(Iref(1:(h-hc),1:(w-wc)),.5);
  S=eye(3); S([1 5])=2; H0=S^-1*H0*S; prm{4}=H0;
  H=imagesAlign1(I1,Iref1,prm); H=S*H*S^-1;
end

% smooth images (pad first so dimensions unchanged)
O=ones(1,(length(filt)-1)/2); hs=[O 1:h h*O]; ws=[O 1:w w*O];
Iref=conv2(conv2(Iref(hs,ws),filt','valid'),filt,'valid');
I=conv2(conv2(I(hs,ws),filt','valid'),filt,'valid');

% pad images with nan so later can determine valid regions
hs=[1 1 1:h h h]; ws=[1 1 1:w w w]; I=I(hs,ws); Iref=Iref(hs,ws);
hs=[1:2 h+3:h+4]; I(hs,:)=nan; Iref(hs,:)=nan;
ws=[1:2 w+3:w+4]; I(:,ws)=nan; Iref(:,ws)=nan;

% convert weights hardcoded for 128x128 image to given image dims
wts=[1 1 1.0204 .03125 1.0313 0.0204 .00055516 .00055516];
s=sqrt(numel(Iref))/128;
wts=[wts(1:2) wts(3)^(1/s) wts(4)/s wts(5)^(1/s) wts(6)/s wts(7:8)/(s*s)];

% prepare subspace around Iref
[~,Hs]=ds2H(-ones(1,8),wts); Hs=Hs(:,:,keep); K=size(Hs,3);
[h,w]=size(Iref); Ts=zeros(h,w,K); k=0;
if(keep(1)), k=k+1; Ts(:,1:end-1,k)=Iref(:,2:end); end
if(keep(2)), k=k+1; Ts(1:end-1,:,k)=Iref(2:end,:); end
pTransf={'method','bilinear','pad','none','useCache'};
for i=k+1:K, Ts(:,:,i)=imtransform2(Iref,Hs(:,:,i),pTransf{:},1); end
Ds=Ts-Iref(:,:,ones(1,K)); Mref = ~any(isnan(Ds),3);
if(0), figure(10); montage2(Ds); end
Ds = reshape(Ds,[],size(Ds,3));

% iteratively project Ip onto subspace, storing transformation
lambda=lambda*w*h*eye(K); ds=zeros(1,8); err=inf;
for i=1:100
  s=svd(H); if(s(3)<=1e-4*s(1)), H=eye(3); return; end
  Ip=imtransform2(I,H,pTransf{:},0); dI=Ip-Iref; dI0=abs(dI);
  M=Mref & ~isnan(Ip); M0=M; if(outThr<inf), M=M & dI0<outThr; end
  M1=find(M); D=Ds(M1,:); ds1=(D'*D + lambda)^(-1)*(D'*dI(M1));
  if(any(isnan(ds1))), ds1=zeros(K,1); end
  ds(keep)=ds1; H1=ds2H(ds,wts); H=H*H1; H=H/H(9);
  err0=err; err=dI0; err(~M0)=0; err=mean2(err); del=err0-err;
  if(0), fprintf('i=%03i err=%e del=%e\n',i,err,del); end
  if( del<epsilon ), break; end
end

end

function [H,Hs] = ds2H( ds, wts )
% compute homography from offsets ds
Hs=eye(3); Hs=Hs(:,:,ones(1,8));
Hs(2,3,1)=wts(1)*ds(1);                       % 1 x translation
Hs(1,3,2)=wts(2)*ds(2);                       % 2 y translation
Hs(1:2,1:2,3)=eye(2)*wts(3)^ds(3);            % 3 scale
Hs(2,1,4)=wts(4)*ds(4);                       % 4 shear
Hs(1,1,5)=wts(5)^ds(5);                       % 5 scale non-uniform
ct=cos(wts(6)*ds(6)); st=sin(wts(6)*ds(6));
Hs(1:2,1:2,6)=[ct -st; st ct];                % 6 rotation about z
ct=cos(wts(7)*ds(7)); st=sin(wts(7)*ds(7));
Hs([1 3],[1 3],7)=[ct -st; st ct];            % 7 rotation about x
ct=cos(wts(8)*ds(8)); st=sin(wts(8)*ds(8));
Hs(2:3,2:3,8)=[ct -st; st ct];                % 8 rotation about y
H=eye(3); for i=1:8, H=Hs(:,:,i)*H; end
end


function WG = slnbreconweights(X0, X, G, varargin)
%SLNBRECONWEIGHTS Solve the optimal reconstruction weights on given neighbors
%
% $ Syntax $
%   - WG = slnbreconweights(X0, X, G, ...)
%
% $ Arguments $
%   - X0:       The reference samples to reconstruct the query samples
%   - X:        The query samples
%   - G:        The graph giving the neighborhood relations
%   - WG:       The weighted graph giving the solved weights
%
% $ Description $
%   - WG = slnbreconweights(X0, X, G, ...) solves the optimal weights to
%     reconstruct the samples in X from those in X0. If X is empty, then
%     it would use X0 as X. The graph G indicates the neighborhood
%     relation, having n0 sources and n targets. The WG is a graph with
%     of the same size as G, and the reconstuction weights are placed
%     in the positions corresponding to those in G.
%     You can specify the following properties to control the solving:
%     \*
%     \t    Table. The Properties of Reconstruction Weights Solving
%     \h       name        &     description
%            'constraint'  & The constraint on the solution, it can be
%                            one of the following string to indicate a
%                            single constraint or a cell array of multiple
%                            strings to indicate compound constaints.
%                            - 'nonneg':  non-negative
%                            - 's1':      the weights sum to 1
%                            (default = 's1')
%            'delta'       & The value of regularization. In practice,
%                            regularization is essential to guarantee the
%                            stability of the solution. In implementation,
%                            the diagonal elements of the gram matrix will
%                            be added with a value:
%                               (delta^2) * trace(G) / K
%                            here G is X^T * X, K is the neighbor number.
%                            (default = 0.1)
%            'solver'      & The solver offered by user (function handle).
%                            If the user specify a non-empty solver, then
%                            it will use the user's solver to solve
%                            weights. The solver is like the form:
%                               w = f(X, y)
%                            Here X is d x K neighbor sample matrix, y is
%                            a d x 1 vector representing the target sample.
%                            It should output a K x 1 vector giving the
%                            reconstruction weights.
%                            By default, solver = [], indicating to use
%                            internal solver based on constraint and delta.
%            'thres'       & The thres, if the ratio of a weight value
%                            to the average weight for that reconstruction
%                            is lower than thres, the weight is set
%                            to strictly zeros. This would significantly
%                            reduces the near-zero weights, and thus
%                            reduces the complexity of the graph.
%                            (default = 1e-8)
%     \*
%
% $ Remarks $
%   - When the user specify a non-empty solver, the internal solver will
%     not be used, thus constraint and delta will not take effect.
%
%   - G would be in all acceptable graph form. WG will always be a
%     numeric matrix. If G is a sparse adjmat, then WG would be sparse,
%     otherwise WG is full.
%
%   - With the WG solved, to reconstruct by weighed combination of
%     neighbors, you can simply write it as: Xr = X0 * WG, then Xr
%     is a d x n matrix with the j-th column reconstructed from the
%     referenced samples in Xr using the j-th column's weights in WG.
%
% $ History $
%   - Created by Dahua Lin, on Sep 11st, 2006
%

%% parse and verify input arguments

if nargin < 3
    raise_lackinput('slnbreconweights', 3);
end

if ~isnumeric(X0) || ndims(X0) ~= 2
    error('sltoolbox:invalidarg', ...
        'X should be a 2D numeric matrix');
end
[d, n0] = size(X0);

if isempty(X)
    X = X0;
else
    if ~isnumeric(X) || ndims(X) ~= 2
        error('sltoolbox:invalidarg', ...
            'X0 should be a 2D numeric matrix');
    end
    if size(X, 1) ~= d
        error('sltoolbox:sizmismatch', ...
            'The sample dimension in X is not the same as that in X0');
    end
end
n = size(X, 2);

gi = slgraphinfo(G);
if gi.n ~= n0 || gi.nt ~= n
    error('sltoolbox:sizmismatch', ...
        'The size of the graph is not consisitent with the sample set');
end

opts.constraint = 's1';
opts.delta = 0.1;
opts.solver = [];
opts.thres = 1e-8;
opts = slparseprops(opts, varargin{:});

thres = opts.thres;

%% Prepare parameters

% prepare graph
if ~strcmp(gi.form, 'adjmat')
    G = sladjmat(G, 'sparse', true, 'valtype', 'logical');
end

% prepare solver
if isempty(opts.solver)

    % parse constraints
    cs = opts.constraint;
    if ~isempty(cs)
        if ~iscell(cs)
            cs = {cs};
        end
        constraint = parse_constraints(cs);
    else
        constraint = parse_constraints({});
    end

    % decide solver
    if ~constraint.nonneg
        delta2 = opts.delta^2;
        if ~constraint.s1
            wsolver = @(X, y) internal_wsolver_unc(X, y, delta2);
        else
            wsolver = @(X, y) internal_wsolver_s1(X, y, delta2);
        end
    else
        optimopts = optimset('Display', 'off', 'LargeScale', 'off');
        if ~constraint.s1
            wsolver = @(X, y) internal_wsolver_nonneg(X, y, opts.delta, optimopts);
        else
            wsolver = @(X, y) internal_wsolver_nonneg_s1(X, y, opts.delta, optimopts);
        end
    end

else
    if ~isa(opts.solver, 'function_handle')
        error('The weight solver should be a function handle');
    end
    wsolver = opts.solver;
end

%% main skeleton

% init WG
if issparse(G)
    WG = spalloc(n0, n, nnz(G));
else
    WG = zeros(n0, n);
end

% solve weights
for i = 1 : n
    nbinds = find(G(:,i));
    if ~isempty(nbinds)
        Xnb = X0(:, nbinds);
        y = X(:,i);
        w = wsolver(Xnb, y);
        if thres > 0
            absw = abs(w);
            curthres = thres * sum(absw) / length(w);
            w(absw < curthres) = 0;
        end
        WG(nbinds, i) = w;
    end
end

%% constraint parsing function

function c = parse_constraints(cs)

ncs = length(cs);

c = struct('nonneg', false, 's1', false);

for i = 1 : ncs
    cname = cs{i};
    if ~ischar(cname)
        error('sltoolbox:invalidarg', ...
            'The constraint should be given in char string');
    end
    switch cname
        case 'nonneg'
            c.nonneg = true;
        case 's1'
            c.s1 = true;
        otherwise
            error('sltoolbox:invalidarg', ...
                'Invalid constraint name for weight solving: %s', cname);
    end
end

%% The internal weight solvers

% unconstrained solver
function w = internal_wsolver_unc(X, y, delta2)

[G, Xty] = compute_G_Xty(X, y, delta2);
w = G \ Xty;

% solver with s1 constraint
function w = internal_wsolver_s1(X, y, delta2)

[G, Xty, K] = compute_G_Xty(X, y, delta2);
wu = G \ [Xty, ones(K, 1)];

w = wu(:,1);
u = wu(:,2);
lambda = (1 - sum(w)) / sum(u);
w = w + lambda * u;

% solver with nonnegative constraint
function w = internal_wsolver_nonneg(X, y, delta, optimopts)

[Xa, ya, K] = augformulate(X, y, delta);
if K <= 20
    w = lsqnonneg(Xa, ya, [], optimopts);
else
    lb = zeros(K, 1);
    w = lsqlin(Xa, ya, [], [], [], [], lb, [], [], optimopts);
end

% solver with nonnegative and s1 constraint
function w = internal_wsolver_nonneg_s1(X, y, delta, optimopts)

[Xa, ya, K] = augformulate(X, y, delta);

Aeq = ones(1, K);
beq = 1;
lb = zeros(K, 1);
w = lsqlin(Xa, ya, [], [], Aeq, beq, lb, [], [], optimopts);

% solver preparation function

function [G, Xty, K] = compute_G_Xty(X, y, delta2)

% compute Xt, G, and Xty
K = size(X, 2);
Xt = X';
G = Xt * X;
Xty = Xt * y;

% regularize
if delta2 > 0
    diaginds = (1:K)*(K+1) - K;
    rv = delta2 * sum(G(diaginds)) / K;
    G(diaginds) = G(diaginds) + rv;
end

function [Xa, ya, K] = augformulate(X, y, delta)

K = size(X, 2);
if delta ~= 0
    Xa = [X; delta * eye(K)];
    ya = [y; zeros(K, 1)];
else
    Xa = X;
    ya = y;
end


% Copyright 2019 Jonas Koenemann, Moritz Diehl, University of Freiburg
% Redistribution is permitted under the 3-Clause BSD License terms. Please
% ensure the above copyright notice is visible in any derived work.
%

function variable

% small number of numeric value comparison
mx = false;
eps = 1e-5;

v1 = [5;2.8;2];
v2 = [1,5.01,3;6,5,4];

%%% constructor
a1 = ocl.casadi.CasadiVariable.Matrix([3,1],mx);
a2 = ocl.casadi.CasadiVariable.Matrix([2,3],mx);
s1 = a1.value;
s2 = a2.value;

f = casadi.Function('f',{s1},{s1});
assert(isequal(full(f(v1)),v1))
f = casadi.Function('f',{s2},{s2});
assert(isequal(full(f(v2)),v2))

%%% horzcat, vertcat, subsref
aTest = [a1,a1,a1;a2];
aTest = aTest(3:5,2);
vTest = [v1,v1,v1;v2];
vTest = vTest(3:5,2);
f = casadi.Function('f',{s1,s2},{aTest(2:3).value});
assert(isequal(full(f(v1,v2)),vTest(2:3)))

%%% subsasgn
aTest(2:3) = 11;
vTest(2:3) = 11;
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% norm
aTest = norm(aTest);
vTest = norm(vTest);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% uplus, uminus
%aTest = -+(+aTest);
%vTest = -+(+vTest);
%f = casadi.Function('f',{s1,s2},{aTest.value});
%assert(isequal(full(f(v1,v2)),vTest))

%%% sum
aTest = [a1,a1,a1;a2];
aTest = sum(aTest);
vTest = [v1,v1,v1;v2];
vTest = sum(vTest);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% mtimes
aTest = [a1,a1,a1;a2] * 4 * s1 * [2,3,4];
vTest = [v1,v1,v1;v2] * 4 * v1 * [2,3,4];
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% transpose
aTest = aTest.';
vTest = vTest.';
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% reshape
aTest = reshape(aTest,15,1);
vTest = reshape(vTest,15,1);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))
aTest = reshape(aTest,[3,5]);
vTest = reshape(vTest,[3,5]);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% triu
aTest = triu(aTest);
vTest = triu(vTest);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% repmat
aTest = repmat(aTest,2,3);
vTest = repmat(vTest,2,3);
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% mpower
% mpower is supported since casadi 3.3
aTest = aTest(:,1:6)^2;
vTest = vTest(:,1:6)^2;
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(all(all(vTest-full(f(v1,v2))< eps)))

%%% mldivide (solve in casadi)
A = [0.2625    0.9289    0.5785;
     0.8010    0.7303    0.2373;
     0.0292    0.4886    0.4588];
b = [0.9631,0.5468,0.5211]';

aA = ocl.casadi.CasadiVariable.Matrix([3,3],mx);
ab = ocl.casadi.CasadiVariable.Matrix([3,1],mx);

sA = aA.value;
sb = ab.value;

aTest = aA\ab;
vTest = A\b;
f = casadi.Function('f',{sA,sb},{aTest.value});
assert(all( abs(full(f(A,b))-vTest) <= eps))

%%% cross
aTest = cross(a1,a2(2,:).');
vTest = cross(v1,v2(2,:).');
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% dot
aTest = dot(a1,a2(2,:).');
vTest = dot(v1,v2(2,:).');
f = casadi.Function('f',{s1,s2},{aTest.value});
assert(isequal(full(f(v1,v2)),vTest))

%%% inv
aTest = inv(aA);
vTest = inv(A);
f = casadi.Function('f',{sA},{aTest.value});
assert( all(all( abs(full(f(A))-vTest) <= eps)))

%%% det
aTest = det(aA);
vTest = det(A);
f = casadi.Function('f',{sA},{aTest.value});
assert( abs(full(f(A))-vTest) <= eps)

%%% trace
aTest = trace(aA);
vTest = trace(A);
f = casadi.Function('f',{sA},{aTest.value});
assert(isequal(full(f(A)),vTest))

%%% diag
aTest = diag(aA);
vTest = diag(A);
f = casadi.Function('f',{sA},{aTest.value});
assert(isequal(full(f(A)),vTest))

%%% polyval
aTest = polyval([2;5;4],a1);
vTest = polyval([2;5;4],v1);
f = casadi.Function('f',{s1},{aTest.value});
assert(isequal(full(f(v1)),vTest))

ab.set([2,5,4].');
aTest = polyval(ab,a1);
vTest = polyval([2,5,4].',v1);
f = casadi.Function('f',{s1},{aTest.value});
assert(isequal(full(f(v1)),vTest))

%%% jacobian
% test against finite diff jacobian
aTest = jacobian(testJacobianFun(a1),a1);
vTest = finiteDiffJac(@testJacobianFun,v1);
f = casadi.Function('f',{s1},{aTest.value});
assert(all(all( abs(full(f(v1))-vTest) <= eps)))

%%% jtimes
aTest = jtimes(testJacobianFun(a1),a1,a1);
vTest = vTest * v1;
f = casadi.Function('f',{s1},{aTest.value});
assert(all(all( abs(full(f(v1))-vTest) <= 10*eps)))

%%% plus,minus,times,power,rdivide
aTest = a1(1).^2*a1(2)+a1(3)-a1(2)./a1(3).\a1(1);
vTest = v1(1).^2*v1(2)+v1(3)-v1(2)./v1(3).\v1(1);
f = casadi.Function('f',{s1},{aTest.value});
assert(isequal(full(f(v1)),vTest))

%%% abs,sqrt,sin,cos,tan,atan,asin,acos,atanh,asinh,acosh,exp,log,tanh,cosh,sinh
aTest = tanh(acosh(atan(a1(1)).^2));
aTest = sinh(aTest * sqrt(a1(2))+asinh(abs(a1(3))-log(sin(a1(2)))));
aTest = cosh(acos(asin(aTest * exp(atanh(cos(a1(3)))).\tan(a1(1))+1)));

vTest = tanh(acosh(atan(v1(1)).^2));
vTest = sinh(vTest * sqrt(v1(2))+asinh(abs(v1(3))-log(sin(v1(2)))));
vTest = cosh(acos(asin(vTest * exp(atanh(cos(v1(3)))).\tan(v1(1))+1)));

f = casadi.Function('f',{s1},{aTest.value});
assert(abs(full(f(v1)) - vTest) < eps)

%%% atan2, times
aTest = atan2(a1(1).^2.*a1(2)+a1(3),atan(a1(1)).^2);
vTest = atan2(v1(1).^2.*v1(2)+v1(3),atan(v1(1)).^2);
f = casadi.Function('f',{s1},{aTest.value});
assert(isequal(full(f(v1)),vTest))

%%% (:)
%aTest = [a1,a1,a1;a2];
%vTest = [v1,v1,v1;v2];
%aTest(:) = 2;
%vTest(:) = 2;
%f = casadi.Function('f',{s1,s2},{aTest.value});
%assert(isequal(full(f(v1,v2)),vTest))

% keep type
assert(isa(aTest,'ocl.casadi.CasadiVariable'));

end

function v = testJacobianFun(x)
  v = x*x(1)+cross([x(1);x(3)^2;x(2)],x);
end

function J = finiteDiffJac(functionHandle,x)
  FDeps = 1e-6;
  fx = functionHandle(x);
  Ncols = numel(x);
  Nrows = numel(fx);
  J = zeros(Nrows,Ncols);
  for k=1:Ncols
    dx = zeros(Ncols,1);
    dx(k) = FDeps;
    J(:,k) = (functionHandle(x+dx) - fx) / FDeps;
  end
end