% This is material illustrating the methods from the book
% Financial Modelling  - Theory, Implementation and Practice with Matlab
% source
% Wiley Finance Series
% ISBN 978-0-470-74489-5
%
% Date: 02.05.2012
%
% Authors:  Joerg Kienitz
%           Daniel Wetterau
%
% Please send comments, suggestions, bugs, code etc. to
% kienitzwetterau_FinModelling@gmx.de
%
% (C) Joerg Kienitz, Daniel Wetterau
%
% Since this piece of code is distributed via the mathworks file-exchange
% it is covered by the BSD license
%
% This code is being provided solely for information and general
% illustrative purposes. The authors will not be responsible for the
% consequences of reliance upon using the code or for numbers produced
% from using the code.

function pathS = MC_BS(S0,r,d,T,sigma,NTime,NSim,NBatches)
%
% Path discretization in a Black-Scholes model
%
%   S0 spot price
%   K the strike price
%   r the riskless rate
%   d the dividend yield
%   sigma the volatility
%   T the maturity
%   NTime number of timesteps
%   NSim number of simulations
%   NBatches number of batches

Delta = T/NTime;                          % The discretisation step

pathS = zeros(NSim,NTime+1,NBatches);
lnS1 = zeros(NSim,NTime+1);               % init the logspot price path
lnS1(:,1)=log(S0*exp(-d*T));              % adjust due to dividend yield

omega = (r-d-0.5*sigma^2) * Delta;

for l = 1:NBatches
    dW = randn(NSim,NTime);               % precompute all randoms

    for i=2:NTime+1
        lnS1(:,i) = lnS1(:,i-1) + omega + sigma* sqrt(Delta)*dW(:,i-1);
    end
    pathS(:,:,l) = exp(lnS1);
end


function npartitions = partn_enum ( n, nmax )

%*****************************************************************************80
%
%% PARTN_ENUM enumerates the partitions of N with maximum element NMAX.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Donald Kreher, Douglas Simpson,
%    Combinatorial Algorithms,
%    CRC Press, 1998,
%    ISBN: 0-8493-3988-X,
%    LC: QA164.K73.
%
%  Parameters:
%
%    Input, integer N, the integer to be partitioned.
%    Normally N must be positive, but for this routine any
%    N is allowed.
%
%    Input, integer NMAX, the maximum element in the partition.
%    Normally, 1 <= NMAX <= N is required,
%    but for this routine any value of NMAX is allowed.
%
%    Output, integer NPARTITIONS is the number of partitions of N
%    with maximum element NMAX.
%
  if ( n <= 0 )

    npartitions = 0;

  elseif ( nmax <= 0 || n < nmax )

    npartitions = 0;

  else

    offset = 1;

    p = npart_table ( n, nmax );

    npartitions = p(n+offset,nmax+offset);

  end

  return
end


function value = sphere_unit_monomial_nd ( n, p )

%*****************************************************************************80
%
%% SPHERE_UNIT_MONOMIAL_ND integrates a monomial on a unit sphere in ND.
%
%  Integration region:
%
%    Points X(1:N) such that
%
%      Sum ( X(1:N)**2 ) == 1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Gerald Folland,
%    How to Integrate a Polynomial Over a Sphere,
%    American Mathematical Monthly,
%    Volume 108, May 2001, pages 446-448.
%
%  Parameters:
%
%    Input, integer N, the dimension of the space.
%
%    Input, integer P(N), the exponents of X(1) through X(N) in the monomial.
%    The exponents P(N) must be nonnegative.
%
%    Output, real SPHERE_UNIT_MONOMIAL_ND, the integral of
%    X1**P(1)*X2**P(2)*...*XN**P(N) over the unit sphere.
%
  for i = 1 : n
    if ( mod ( p(i), 2 ) == 1 )
      value = 0.0E+00;
      return
    end
  end

  temp = 0.0E+00;
  arg2 = 0.0E+00;

  for i = 1 : n
    arg1 = ( p(i) + 1 ) / 2.0E+00;
    temp = temp + gammaln ( arg1 );
    arg2 = arg2 + arg1;
  end
  temp = temp - gammaln ( arg2 );

  value = 2.0E+00 * exp ( temp );

  return
end


%% Machine Learning Online Class - Exercise 1: Linear Regression

%  Instructions
%  ------------
%
%  This file contains code that helps you get started on the
%  linear exercise. You will need to complete the following functions
%  in this exericse:
%
%     warmUpExercise.m
%     plotData.m
%     gradientDescent.m
%     computeCost.m
%     gradientDescentMulti.m
%     computeCostMulti.m
%     featureNormalize.m
%     normalEqn.m
%
%  For this exercise, you will not need to change any code in this file,
%  or any other files other than those mentioned above.
%
% x refers to the population size in 10,000s
% y refers to the profit in $10,000s
%

%% Initialization
clear ; close all; clc

%% ==================== Part 1: Basic Function ====================
% Complete warmUpExercise.m
fprintf('Running warmUpExercise ... \n');
fprintf('5x5 Identity Matrix: \n');
warmUpExercise()

%fprintf('Program paused. Press enter to continue.\n');
%pause;

%% ======================= Part 2: Plotting =======================
fprintf('Plotting Data ...\n')
data = load('ex1data1.txt');
X = data(:, 1); y = data(:, 2);
m = length(y); % number of training examples

% Plot Data
% Note: You have to complete the code in plotData.m
plotData(X, y);

%fprintf('Program paused. Press enter to continue.\n'); pause;

%% =================== Part 3: Gradient descent ===================
fprintf('Running Gradient Descent ...\n')

X = [ones(m, 1), data(:,1)]; % Add a column of ones to x
theta = zeros(2, 1); % initialize fitting parameters

% Some gradient descent settings
iterations = 1500;
alpha = 0.01;

% compute and display initial cost
computeCost(X, y, theta)

% run gradient descent
theta = gradientDescent(X, y, theta, alpha, iterations);

% print theta to screen
fprintf('Theta found by gradient descent: ');
fprintf('%f %f \n', theta(1), theta(2));

% Plot the linear fit
hold on; % keep previous plot visible
plot(X(:,2), X*theta, '-')
legend('Training data', 'Linear regression')
hold off % don't overlay any more plots on this figure

% Predict values for population sizes of 35,000 and 70,000
predict1 = [1, 3.5] *theta;
fprintf('For population = 35,000, we predict a profit of %f\n',...
    predict1*10000);
predict2 = [1, 7] * theta;
fprintf('For population = 70,000, we predict a profit of %f\n',...
    predict2*10000);

%fprintf('Program paused. Press enter to continue.\n'); pause;

%% ============= Part 4: Visualizing J(theta_0, theta_1) =============
fprintf('Visualizing J(theta_0, theta_1) ...\n')

% Grid over which we will calculate J
theta0_vals = linspace(-10, 10, 100);
theta1_vals = linspace(-1, 4, 100);

% initialize J_vals to a matrix of 0's
J_vals = zeros(length(theta0_vals), length(theta1_vals));

% Fill out J_vals
for i = 1:length(theta0_vals)
    for j = 1:length(theta1_vals)
	  t = [theta0_vals(i); theta1_vals(j)];
	  J_vals(i,j) = computeCost(X, y, t);
    end
end

% Because of the way meshgrids work in the surf command, we need to
% transpose J_vals before calling surf, or else the axes will be flipped
J_vals = J_vals';
% Surface plot
figure;
surf(theta0_vals, theta1_vals, J_vals)
xlabel('\theta_0'); ylabel('\theta_1');

% Contour plot
figure;
% Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20))
xlabel('\theta_0'); ylabel('\theta_1');
hold on;
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);


function p = predictOneVsAll(all_theta, X)
%PREDICT Predict the label for a trained one-vs-all classifier. The labels
%are in the range 1..K, where K = size(all_theta, 1).
%  p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions
%  for each example in the matrix X. Note that X contains the examples in
%  rows. all_theta is a matrix where the i-th row is a trained logistic
%  regression theta vector for the i-th class. You should set p to a vector
%  of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2
%  for 4 examples)

m = size(X, 1);
num_labels = size(all_theta, 1);

% You need to return the following variables correctly
p = zeros(size(X, 1), 1);

% Add ones to the X data matrix
X = [ones(m, 1) X];

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters (one-vs-all).
%               You should set p to a vector of predictions (from 1 to
%               num_labels).
%
% Hint: This code can be done all vectorized using the max function.
%       In particular, the max function can also return the index of the
%       max element, for more information see 'help max'. If your examples
%       are in rows, then, you can use max(A, [], 2) to obtain the max
%       for each row.
%

for c = 1:m
	one_example = X(c,:);
	[max_value, max_index] = max(all_theta * one_example');
	p(c,1) = max_index;

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

end


function h = qq_plot(varargin)
%  Quantile-quantile plot with patch option
%
%   QQ_PLOT(Y) displays a quantile-quantile plot of the sample quantiles of
%   Y versus theoretical quantiles from a normal distribution. If the
%   distribution of Y is normal, the plot will be close to linear.
%
%   QQ_PLOT(X,Y) displays a quantile-quantile plot of two samples. If the
%   samples come from the same distribution, the plot will be linear.
%
%   The inputs X and Y should be numeric and have an equal number of
%   elements; every element is treated as a member of the sample.
%
%   The plot displays the sample data with the plot symbol 'x'.
%   Superimposed on the plot is a dashed straight line connecting the first
%   and third quartiles.
%
%   QQ_PLOT(...,MODE) allows the appearance of the plot to be configured.
%   With MODE='line' (default), the plot appears as described above. With
%   MODE='patch', the data are plotted as a patch object, with the area
%   bound by the x-distribution and the linear fit shaded grey. With
%   mode='both' the two appearances are combined.
%
%   QQ_PLOT(...,MODE,METHOD) and QQ_PLOT(...,[],METHOD) allows the method
%   for calculating the quartiles, used for the fit line, to be specified.
%   The default is 'R-8'. Type 'help quantile2' for more information. The
%   latter form of the function call uses the default mode.
%
%   H = QQ_PLOT(...) returns a two- or three-element vector of handles to
%   the plotted object. The nature of the handles depends upon the mode. In
%   all cases, the first handle is to the sample data, the second handle is
%   to the fit line. With MODE='patch' or MODE='both', there is third
%   handle to the patch object.
%
%   Example
%
%      % Display Q-Q plots for the rand and randn functions
%      figure
%      subplot(2,1,1)
%      qq_plot(rand(20),'patch')
%      subplot(2,1,2)
%      h = qq_plot(randn(20),'patch');
%      set(h(3),'FaceColor','r') % change fill color

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LICENSE FILE:
% -----------------------------------------------------------------------
% Copyright (c) 2015, Christopher Hummersone
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% ==========================================================
% Last changed:     $Date: 2015-05-20 16:28:56 +0100 (Wed, 20 May 2015) $
% Last committed:   $Revision: 380 $
% Last changed by:  $Author: ch0022 $
% ==========================================================

    %% determine X and Y

    IXn = cellfun(@(x) isnumeric(x) & ~isempty(x),varargin);

    switch sum(IXn)
        case 0
            error('No input data specified')
        case 1
            % compare to normal distrbution
            Y = get_input_sample(varargin,IXn);
            p = (.5:length(Y))/length(Y);
            X = sqrt(2)*erfinv(2*p - 1);
            x_label = 'Standard normal quantiles';
            y_label = 'Sample quantiles';
        case 2
            % compare to input data distribution
            Y = get_input_sample(varargin,find(IXn,1,'last'));
            X = get_input_sample(varargin,find(IXn,1,'first'));
            assert(isequal(size(X),size(Y)),'Input data must be the same size')
            x_label = 'X quantiles';
            y_label = 'Y quantiles';
        otherwise
            error('Unknown input specified')
    end

    %% determine mode and method

    % find inputs
    IXc = cellfun(@(x) ischar(x) | isempty(x),varargin);
    switch sum(IXc)
        case 0
            mode = [];
            method = [];
        case 1
            mode = varargin{IXc};
            method = [];
        case 2
            mode = varargin{find(IXc,1,'first')};
            method = varargin{find(IXc,1,'last')};
        otherwise
            error('Unknown string specified')
    end

    % defaults
    if isempty(mode)
        mode = 'line';
    end
    if isempty(method)
        method = 'R-8';
    end

    %% calculate fit to first and third quartile

    % quartiles
    q1x = quantile2(X,.25,[],method);
    q3x = quantile2(X,.75,[],method);
    q1y = quantile2(Y,.25,[],method);
    q3y = quantile2(Y,.75,[],method);

    % slope
    slope = (q3y-q1y)./(q3x-q1x);
    centerx = (q1x+q3x)/2;
    centery = (q1y+q3y)/2;

    % fit
    maxx = max(X);
    minx = min(X);
    maxy = centery + slope.*(maxx - centerx);
    miny = centery - slope.*(centerx - minx);

    % lines
    X_fit = linspace(minx,maxx,length(X));
    Y_fit = linspace(miny,maxy,length(X));

    %% plot data

    hold on

    if strcmpi(mode,'patch') || strcmpi(mode,'both')
        Hp = patch([X fliplr(X_fit)],[Y fliplr(Y_fit)],[0.5 0.5 0.5]);
        set(Hp,'edgecolor','none')
    else
        Hp = NaN;
    end

    switch lower(mode)
        case 'line'
            linestyle = 'xk';
        case 'patch'
            linestyle = '-k';
        case 'both'
            linestyle = 'xk';
        otherwise
            error('Unknown mode specified')
    end

    H = plot(X,Y,linestyle,X_fit,Y_fit,'--k');

    hold off

    % axis labels
    xlabel(x_label)
    ylabel(y_label)

    box on; axis tight
    set(gca,'layer','top')

    % return handle
    if nargout>0
        h = H;
        if isobject(Hp) || ishandle(Hp)
            h = [h; Hp];
        end
    end

end

function Z = get_input_sample(z,IX)
%GET_INPUT_SAMPLE get sample, order, and convert to vector
    Z = z{IX};
    Z = sort(Z(:))';
end


function gb=gabor_fn(bw,gamma,psi,lambda,theta)
% bw    = bandwidth, (1)
% gamma = aspect ratio, (0.5)
% psi   = phase shift, (0)
% lambda= wave length, (>=2)
% theta = angle in rad, [0 pi)

sigma = lambda/pi*sqrt(log(2)/2)*(2^bw+1)/(2^bw-1);
sigma_x = sigma;
sigma_y = sigma/gamma;

sz=fix(8*max(sigma_y,sigma_x));
if mod(sz,2)==0, sz=sz+1;end

% alternatively, use a fixed size
% sz = 60;

[x y]=meshgrid(-fix(sz/2):fix(sz/2),fix(sz/2):-1:fix(-sz/2));
% x (right +)
% y (up +)

% Rotation
x_theta=x*cos(theta)+y*sin(theta);
y_theta=-x*sin(theta)+y*cos(theta);

gb=exp(-0.5*(x_theta.^2/sigma_x^2+y_theta.^2/sigma_y^2)).*cos(2*pi/lambda*x_theta+psi);
imshow(gb/2+0.5);


function F = tempCompCurve(x,Tdata)
%% Calculate Temperature Curve given Resistor and Thermistor Values
% Copyright (c) 2012, MathWorks, Inc.
%% Input voltage
Vin = 1.1;

%% Thermistor Calculations
% Values in x: R1 R2 R3 R4 RTH1(T_25degc) Beta1 RTH2(T_25degc) Beta2
% Thermistors are represented by:
%   Room temperature is 25degc: T_25
%   Standard value is at 25degc: RTHx_25
%   RTHx is the thermistor resistance at various temperature
% RTH(T) = RTH(T_25degc) / exp (Beta * (T-T_25)/(T*T_25)))
T_25 = 298.15;
T_off = 273.15;
Beta1 = x(6);
Beta2 = x(8);
RTH1 = x(5) ./ exp(Beta1 * ((Tdata+T_off)-T_25)./((Tdata+T_off)*T_25));
RTH2 = x(7) ./ exp(Beta2 * ((Tdata+T_off)-T_25)./((Tdata+T_off)*T_25));

%% Define equivalent circuits for parallel R's and RTH's
R1_eq = x(1)*RTH1./(x(1)+RTH1);
R3_eq = x(3)*RTH2./(x(3)+RTH2);

%% Calculate voltages at Point B
F = Vin * (R3_eq + x(4))./(R1_eq + x(2) + R3_eq + x(4));


% Isoparametric Formulation Implementation
% clear memory
clear all

%% Physical Parameters
% numberElements: number of elements
numberElements = 6;

% Initial Area
A = 12.5e-4; % m^2

% Modulus of elasticity
E = 2e11; % N/m^2

% Length of bar
Ltotal = 1.5; % m

%% Exact solutions
xx = 0:0.1:1.5;
displacements_exact = (40000*xx.^3/3-45000)/(E*A);
stress_exact = (40000*xx.^2)/A;

figure(3)

% Displacements
subplot(1,2,1); hold on;
plot(xx,displacements_exact,'-r');

% Stress
subplot(1,2,2); hold on;

plot(xx,stress_exact,'-r');

test = [1 2 4 8];
for numberElements = test

% Build nodes coordinates and middle points,
delta_x = Ltotal/numberElements;
i = 0:numberElements;
x = delta_x*i';x_mid = (x(2:end)-x(1:end-1))/2 + x(1:end-1);

% Length of each element
L = x(2:end)-x(1:end-1);

%% Build Elements
% numberNodes: number of nodes
numberNodes = numberElements + 1;

% generation of coordinates and connectivities
elementNodes = zeros(numberElements,2);
elementNodes(1,:) = [1,2];
for i = 2:numberElements
    elementNodes(i,:) = elementNodes(i-1,:) + 1;
end
nodeCoordinates = x;

% for structure:
   % displacements: displacement vector
   % force : force vector
   % stiffness: stiffness matrix
force=zeros(numberNodes,1);
stiffness=zeros(numberNodes,numberNodes);
% computation of the system stiffness matrix and force vector
for e=1:numberElements;
  % elementDof: element degrees of freedom (Dof)
  elementDof=elementNodes(e,:) ;
  detJacobian=L(e)/2;
  invJacobian=1/detJacobian;
  ngp = 2;
  [w,xi]=gauss1d(ngp);
  xc=0.5*(nodeCoordinates(elementDof(1))+nodeCoordinates(elementDof(2)));
  for ip=1:ngp;
      [shape,naturalDerivatives]=shapeFunctionL2(xi(ip));
      B=naturalDerivatives*invJacobian;
      stiffness(elementDof,elementDof)=...
      stiffness(elementDof,elementDof)+ B'*B*w(ip)*detJacobian*E*A;
      force(elementDof) = force(elementDof)+...
          -80000*(xc+detJacobian*xi(ip))*shape'*detJacobian*w(ip);
  end
end

%% BCs and solution
% prescribed dofs
prescribedDof = find(nodeCoordinates == 1.5); % fixed at node x = 1.5 m
% solution
GDof=numberNodes;
displacements=solution(GDof,prescribedDof,stiffness,force);
% output displacements/reactions
outputDisplacementsReactions(displacements,stiffness, ...
    numberNodes,prescribedDof,force)

%% Stress
stress = zeros(numberElements,1);
for e=1:numberElements;
    stress(elementNodes(e,:)) = E*B*displacements(elementNodes(e,:));
end

%% plot figures

switch numberElements
    case 1
        line='r*--';
    case 2
        line='g*--';
    case 4
        line='k*--';
    case 8
        line='m*--';
end

% Displacements
subplot(1,2,1); plot(nodeCoordinates,displacements,line)

% Stress
subplot(1,2,2); stairs(nodeCoordinates,stress,line)

end %end for
subplot(1,2,1); legend('Exact','NEL=1','NEL=2','NEL=4','NEL=8',2); hold off
subplot(1,2,2); legend('Exact','NEL=1','NEL=2','NEL=4','NEL=8',2); hold off


%
% Implementation of Bertsekas' auction algorithm [1] for a very fast
% solution of the linear assignment problem, i.e. it is able
% to solve a 1000-by-1000 problem in ~1.5s.
%
% In practice, with respect to running time, the auction algorithm
% outperforms the Kuhn-Munkres (or Hungarian) algorithm significantly.
% The auction algorithm has average run-time complexity O(N^2*log(N)) and
% worst-case complexity O(N^3), whereas the Kuhn-Munkres algorithm has
% average- and worst-case complexity  O(N^3).
%
% Note that only global optima are found for integer-valued benefit matrices.
% For real-valued benefit matrices a scaling of the values needs to be applied
% by multiplication with a large number. This scaling factor depends on the
% desired accuracy, as the global solution is found for the integral part
% of the benefit matrix, whilst there is no guarantee that the fractional part
% of the benefits are properly taken into account. However, in practical cases
% it seems advantageous to not round the resulting benefit matrix and retain
% the fractional parts in the benefit matrix. Also note that larger scalings
% of the benefit matrix increase the run-time, so a problem-specific trade-off
% between runtime and accuracy must be chosen.
%
% Runtime can be slightly decreased by installing the FastSet library,
% available on
% http://www.levmuchnik.net/Content/ProgrammingTips/MatLab/FastSet/FastSet.html
%
% Input:
%               A                       N-by-N benefit matrix (higher
%                                       values indicate a better match)
%               [epsilon]               Initial value of epsilon (optional)
%               [epsilonDecreaseFactor] Decreas factor of epsilon
%                                       (optional)
%
% Output:
%               assignments             Resulting assignments
%               [prices]                Prices used during auctions
%                                       (optional)
%
% Example:      See the function test() below for a usage example.
%               Typically only the benefit matrix A is given as input and the
%               first output argument is relevant. epsilon and
%               epsilonDecreaseFactor can be used to heuristically adapt
%               runtime. The example below can also be used for testing
%               whether a sufficient amount of scaling has been performed.
%               This is done by solving the assignment problem using CVX
%               (available on http://cvxr.com/cvx/download/ ) and comparing
%               its result to the solution with the auction algorithm.
%
%
% [1]	Bertsekas, D.P. 1998. Network Optimization Continuous and Discrete Models.
%
% Implementation by Florian Bernard ( f.bernardpi [at] gmail [dot] com )
%
% Created on 25/07/2014

function [assignments, prices] = ...
    assignmentProblemAuctionAlgorithm(A, epsilon, epsilonDecreaseFactor)

N = size(A,1);
assignments = nan(N,1);
prices = ones(N,1);

% check which unique function we use
if ( exist('fast_unique', 'file') )
    % requires FastSet, available on
    % http://www.levmuchnik.net/Content/ProgrammingTips/MatLab/FastSet/FastSet.html
    uniqueFcn = @fast_unique;
else
    uniqueFcn = @unique;
end

% heuristic for setting epsilon
A = A*(N+1);
if ( ~exist('epsilon', 'var') || isempty(epsilon) )
    maxAbsA = max(abs(A(:)));
    epsilon = maxAbsA/25;
%     if ( sum(abs(A(:)) > 0.0001) > 0.7*N*N ) % non-sparse
%         ...
%     else
%         epsilon = 0.5*((N*maxVal)/5 + N*maxVal); % see page 260 in [1]
%     end
end

if ( ~exist('epsilonDecreaseFactor', 'var') )
    epsilonDecreaseFactor = 0.2;
end

while (epsilon >= 1)
    % the outer loop performs epsilon-scaling in order to speed up execution
    % time. In particular, an updated prices array is computed in each
    % round, which speeds up further rounds with lower values of epsilon.
    assignments = nan(N,1);
    while (any(isnan(assignments)))
    %% forward-auction algorithm
        %% bidding phase
        % find unassigned indices
        unassignedIdx = find(isnan(assignments));
        nUnassigned = numel(unassignedIdx);

        % find best and second best objects
        AijMinusPj = bsxfun(@minus, A(unassignedIdx,:), prices');

        [~,viIdx] = max(AijMinusPj, [], 2);

        for i=1:nUnassigned
            AijMinusPj(i,viIdx(i)) = -inf;
        end
        wi = max(AijMinusPj, [], 2);

        % compute bids
        bids = nan(nUnassigned,1);
        for i=1:nUnassigned
            bids(i) = A(unassignedIdx(i),viIdx(i)) - wi(i) + epsilon;
        end

        %% assignment phase
        objectsThatHaveBeenBiddedFor = uniqueFcn(viIdx);
        for uniqueObjIdx=1:numel(objectsThatHaveBeenBiddedFor)
            currObject = objectsThatHaveBeenBiddedFor(uniqueObjIdx);
            personssWhoGaveBidsForJ = find(viIdx==currObject);

            [prices(currObject), idx] = max(bids(personssWhoGaveBidsForJ));
            personWithHighestBid = unassignedIdx(personssWhoGaveBidsForJ(idx));

            % remove previous assignment and store new assignment (the person
            % with highest bid)
            assignments(assignments==currObject) = nan;
            assignments(personWithHighestBid) = currObject;

        end
    end
    epsilon = epsilon * epsilonDecreaseFactor; % refine epsilon
end
end

function test()
N = 1000;

X = rand(N,3);
reference = rand(N,3);

A = X*reference';
%% Apply Auction algorithm
tic
    % scale A such that the integer version of A has sufficient accuracy
    % if S1 and P are not equal, the scaling factor needs to be increased
    scalingFactor = 10^6;
    Ascaled = A*scalingFactor;

    [assignments] = assignmentProblemAuctionAlgorithm(Ascaled);

    % create permutation matrix from assignments
    linIdx = sub2ind(size(A),assignments',1:size(A,1));
    P = sparse(size(A,1),size(A,2));
    P(linIdx) = 1;
toc

%% Use CVX for checking correctness of result
%  (Useful in particular for non-integer matrices A)
%  Note that this is really slow as CVX needs to create the canonical form
%  of the LP before it can call Gurobi. Creating the canonical form by hand
%  and directly calling Gurobi is much faster.
E = ones(N,1);

tic
    cvx_begin % quiet
        cvx_solver gurobi % uncomment this line if Gurobi is not available
        variable S1(N,N) nonnegative;
        maximize (trace(S1*A));
        S1*E==E;
        E'*S1==E';
    cvx_end
toc

% check if results are equal
if ( sum(sum(full(S1)~=full(P))) == 0 )
    disp('Correct results using Auction algorithm');
else
    error('Incorrect results using Auction algorithm. You probably need to scale A by a larger factor!');
end
end


function [C, sigma] = dataset3Params(X, y, Xval, yval)
%DATASET3PARAMS returns your choice of C and sigma for Part 3 of the exercise
%where you select the optimal (C, sigma) learning parameters to use for SVM
%with RBF kernel
%   [C, sigma] = DATASET3PARAMS(X, y, Xval, yval) returns your choice of C and
%   sigma. You should complete this function to return the optimal C and
%   sigma based on a cross-validation set.
%

% You need to return the following variables correctly.
C = 1;
sigma = 0.3;

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the optimal C and sigma
%               learning parameters found using the cross validation set.
%               You can use svmPredict to predict the labels on the cross
%               validation set. For example,
%                   predictions = svmPredict(model, Xval);
%               will return the predictions on the cross validation set.
%
%  Note: You can compute the prediction error using
%        mean(double(predictions ~= yval))
%

C_s = [0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30];
sigma_s = C_s ;
l = length(C_s);
scores = zeros(l);
for i = 1:l
    for j = 1:l
        C = C_s(i);
        sigma = sigma_s(j);
        model= svmTrain(X, y, C, @(x1, x2) gaussianKernel(x1, x2, sigma));
        predictions = svmPredict(model, Xval);
        scores(i, j) = mean(double(predictions ~= yval));
    end
end

s = scores;
[~, j] = min(min(s));
[~, temp] = min(s);
i = temp(j);
C = C_s(i);
sigma = sigma_s(j);
% =========================================================================

end


function [SNR] = bvpsnr(BVP, FS, HR, PlotTF)
%BVPSNR Estimates the signal-to-noise ratio of the blood volume pulse
% signal. Adapted from the method by G. de Haan, TBME, 2013.
% SNR calculated as the ratio (in dB) of power contained within +/- 0.1 Hz
% of the reference heart rate frequency and +/- 0.2 of its first
% harmonic and sum of all other power between 0.5 and 4 Hz.
% Adapted from the method by G. de Haan, TBME, 2013
%
%   Inputs:
%       BVP                     = A BVP timeseries.
%       FS                      = The sample rate of the BVP time series (Hz/fps).
%       HR                      = The reference heart rate (Hz/fps).
%       PlotTF                  = Boolean to turn plotting results on or off.
%
%   Outputs:
%       SNR                     = Blood Volume Pulse Signal-to-Noise Ratio.
%
% Daniel McDuff, Ethan Blackford, January 2019
% Copyright (c)
% Licensed under the MIT License and the RAIL AI License.

HR_F=HR/60;

NyquistF = FS/2;
FResBPM = 0.5; %resolution (bpm) of bins in power spectrum used to determine PR and SNR
N = (60*2*NyquistF)/FResBPM; %number of bins in power spectrum

%% Construct Periodogram
[Pxx,F] = periodogram(BVP,hamming(length(BVP)),N,FS);
GTMask1 = (F >= HR_F-0.1)&(F <= HR_F+0.1);
GTMask2 = (F >= HR_F*2-0.2)&(F <= HR_F*2+0.2);
SPower = sum(Pxx(GTMask1|GTMask2));
FMask2 = (F >= 0.5)&(F <= 4);
AllPower = sum(Pxx(FMask2));
SNR = pow2db(SPower/(AllPower-SPower));

%% Optionally plot the power spectrum and regions used to calculate the SNR
if(PlotTF)
    % Plot spower spectrum and SNR regions
    figure
    plot(F,pow2db(Pxx))
    title('Power Spectrum and SNR Regions')
    xlabel('Frequency (Hz)')
    ylabel('Power (dB)')
    xlim([0.5 4])
    ylimreg=ylim;
    hold on

    % HR peak
    %line([HR_F,HR_F],ylim,'Color','magenta','LineStyle','-.')

    % HR peak region
    line([HR_F-0.1,HR_F-0.1],ylim,'Color','red','LineStyle','--')
    line([HR_F+0.1,HR_F+0.1],ylim,'Color','red','LineStyle','--')

    % First harmonic
    line([HR_F*2-0.2,HR_F*2-0.2],ylim,'Color','red','LineStyle','--')
    line([HR_F*2+0.2,HR_F*2+0.2],ylim,'Color','red','LineStyle','--')

    % Overall power region
    line([0.5,0.5],ylim,'Color','black','LineStyle','-')
    line([4,4],ylim,'Color','black','LineStyle','-')

    % Adjust axes
    xlim([0 4.5])
    ylim(ylimreg);
end

end


function geometry_test1895 ( )

%*****************************************************************************80
%
%% TEST1895 tests SPHERE_UNIT_AREA_ND, SPHERE_UNIT_AREA_VALUES.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2005
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST1895:\n' );
  fprintf ( 1, '  SPHERE_UNIT_AREA_ND evaluates the area of the unit\n' );
  fprintf ( 1, '  sphere in N dimensions.\n' );
  fprintf ( 1, '  SPHERE_UNIT_AREA_VALUES returns some test values.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '     DIM_NUM    Exact          Computed\n' );
  fprintf ( 1, '             Area           Area\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, dim_num, area ] = sphere_unit_area_values ( n_data );

    if ( n_data == 0 )
      break
    end

    area2 = sphere_unit_area_nd ( dim_num );

    fprintf ( 1, '  %6d  %10f  %10f\n', dim_num, area, area2 );

  end

  return
end


function result = intersect2(cell)

% PURPOSE:
%   This function finds the common elements of several 1D numeric arrays
%   of the same or different sizes and returns an array consisting of only
%   those elements.
%
% INPUT:
%   The input variable "cell" has to be a cell array, with each cell
%   occupied by an 1D numeric array. For example, if you want to find the
%   intersection (common elements) of the following three arrays
%       a = [ 1 3 4 6 8 9 ];
%       b = [ 3 1 0 8 6 4 ];
%       c = [ 7 8 1 9 3 4 ];,
%   you need to first put all of them into a cell array, i.e.
%       cell = {a, b, c};
%   Then you could use "cell" as the input variable to this function, i.e.
%       result = intersect2(cell);
%
% OUTPUT:
%   The output of this function is simply an array consisting of elements
%   that are common to all the arrays stored in "cell". For the particular
%   case in the example above, the output would be
%       result = [ 1 3 4 8 ];
%   Also note that the numbers in the result are sorted in ascending order.

n = max(size(cell));

if n == 2
    result = intersect(cell{1, 1}, cell{1, 2});
elseif (n > 2 && rem(n,2) == 0)
    for i = 1:(n/2)
        intersections{1, i} = intersect(cell{1, i}, cell{1, n-i+1});
    end
elseif (n > 2 && rem(n,2) == 1)
    for i = 1:((n-1)/2)
        intersections{1, i} = intersect(cell{1, i}, cell{1, n-i+1});
    end
        intersections{1, i+1} = cell{1, (n+1)/2};
else
    error('You need at least two arrays as inputs');
end

if n > 2
    result = intersect2(intersections);
end


function numgrad = computeNumericalGradient(J, theta)
% numgrad = computeNumericalGradient(J, theta)
% theta: a vector of parameters
% J: a function that outputs a real-number. Calling y = J(theta) will return the
% function value at theta.

% Initialize numgrad with zeros
numgrad = zeros(size(theta));

%% ---------- YOUR CODE HERE --------------------------------------
% Instructions:
% Implement numerical gradient checking, and return the result in numgrad.
% (See Section 2.3 of the lecture notes.)
% You should write code so that numgrad(i) is (the numerical approximation to) the
% partial derivative of J with respect to the i-th input argument, evaluated at theta.
% I.e., numgrad(i) should be the (approximately) the partial derivative of J with
% respect to theta(i).
%
% Hint: You will probably want to compute the elements of numgrad one at a time.

epsilon = 1e-4;

for i =1:length(numgrad)
    oldT = theta(i);
    theta(i)=oldT+epsilon;
    pos = J(theta);
    theta(i)=oldT-epsilon;
    neg = J(theta);
    numgrad(i) = (pos-neg)/(2*epsilon);
    theta(i)=oldT;
    if mod(i,100)==0
       fprintf('Done with %d\n',i);
    end;
end;

%% ---------------------------------------------------------------
end


function p = predict(theta, X)
%PREDICT Predict whether the label is 0 or 1 using learned logistic
%regression parameters theta
%   p = PREDICT(theta, X) computes the predictions for X using a
%   threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1)

m = size(X, 1); % Number of training examples

% You need to return the following variables correctly
p = zeros(m, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters.
%               You should set p to a vector of 0's and 1's
%

for i=1:m,
	if sigmoid(X(i,:)*theta) >= 0.5,
		p(i) = 1;
	else
		p(i) = 0;
	end;
end;

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

end


function gZ = vrate(Z,s)
% PURPOSE: Compute the year-on-year rate of growth of a vector time series
% ------------------------------------------------------------------------
% SYNTAX:  gZ = vrate(Z,s);
% ------------------------------------------------------------
% OUTPUT: gZ: nxk --> yoy rate of growth. First s obs are NaN
% ------------------------------------------------------------
% INPUT:  Z: nxk --> vector time series to be filtered
%         s: 1x1 --> number of periods per year
% ------------------------------------------------------------
% LIBRARY: rate
% -----------------------------------------------------------------------

% written by:
%  Enrique M. Quilis
%  Macroeconomic Research Department
%  Ministry of Economy and Competitiveness
%  <enrique.quilis@mineco.es>

% Version 1.1 [August 2006]

[n,k] = size(Z);

% Preallocation
gZ = NaN * ones(n,k);

% Basic loop
for j=1:k
    gz = rate(Z(:,j),s);
    gZ(:,j) = gz;
end


function ds = dsegment ( p, pv )

%*****************************************************************************80
%
%% DSEGMENT computes the distance of points to line segments.
%
%  Discussion:
%
%    This is a pure MATLAB version of the DSEGMENT routine.
%    Normally, the authors of DISTMESH recommend using a faster procedure
%    in which a MATLAB MEX interface is used to call a compiled C code.
%    But if that is not possible, you can fall back on this slower
%    version.
%
%    Note that the line segments are defined by successive pairs of
%    vertices.  In the very common case that the vertices represent
%    a polygon, it is necessary that the list be extended by repeating
%    the first vertex at the end; otherwise the definition of the
%    polygon, and the distance computation, will be incomplete.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Parameters:
%
%    Input, real P(NP,2), a set of points.
%
%    Input, real PV(NVS,2), a set of vertices.  Sequential
%    pairs define NVS-1 line segments.
%
%    Output, real DS(NP,NVS-1); DS(I,J) is the (unsigned) distance
%    of point P(I,:) from line segment PV(J,:)--PV(J+1,:).
%
  nvs = size ( pv, 1 );
  np = size ( p, 1 );

  ds = zeros ( np,nvs-1);

  for iv = 1 : nvs-1
    for ip = 1 : np

      v(1:2) = [ pv(iv+1,1) - pv(iv,1), pv(iv+1,2) - pv(iv,2) ];

      w(1:2) = [ p(ip,1) - pv(iv,1), p(ip,2) - pv(iv,2) ];

      c1 = v * w';
      c2 = v * v';

      if ( c1 <= 0.0 )
        ds(ip,iv) = sqrt ( sum ( ( p(ip,1:2) - pv(iv,1:2) ).^2 ) );
      elseif ( c2 <= c1 )
        ds(ip,iv) = sqrt ( sum ( ( p(ip,1:2) - pv(iv+1,1:2) ).^2 ) );
      else
        ds(ip,iv) = sqrt ( sum ( ( p(ip,1:2) ...
          - pv(iv,1:2) - c1 / c2 * v(1:2) ).^2 ) );
      end

    end
  end

  return
end


%wrap - Set radian angles in range [0,2pi] or [-pi,pi].
%
%  USAGE
%
%    y = wrap(x,range)
%
%    x              angles in radians
%    range          optional:  1 for [-pi,pi] (default)
%                              2 for [0,2pi]
%
%  SEE ALSO
%
%    See also isradians.
%

% Copyright (C) 2010-2011 by Michaël Zugaro
%
% 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 3 of the License, or
% (at your option) any later version.

function y = wrap(x,range)

% Check number of parameters
if nargin < 1,
  error('Incorrect number of parameters (type ''help wrap'' for details).');
end

if nargin < 2,
	range = 1;
end

if ~isa(x,'double'), y = []; return; end

% Determine angle in [0,2*pi]
y = mod(x,2*pi);

% Change range if necessary
if range == 1,
	change = y > pi;
	y(change) = y(change)-2*pi;
end


function sine_transform_test01 ( )

%*****************************************************************************80
%
%% SINE_TRANSFORM_TEST01 demonstrates that the transform is its own inverse.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 February 2012
%
%  Author:
%
%    John Burkardt
%
  n = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SINE_TRANSFORM_TEST01:\n' );
  fprintf ( 1, '  SINE_TRANSFORM_DATA does a sine transform of data\n' );
  fprintf ( 1, '  defined by a vector.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Demonstrate that the transform is its own inverse.\n' );
  fprintf ( 1, '  Let R be a random N vector.\n' );
  fprintf ( 1, '  Let S be the transform of D.\n' );
  fprintf ( 1, '  Let T be the transform of E.\n' );
  fprintf ( 1, '  Then R and T will be equal.\n' );

% r = rand ( n, 1 );
  seed = 123456789;
  [ r, seed ] = r8vec_uniform_01 ( n, seed );
  s = sine_transform_data ( n, r );
  t = sine_transform_data ( n, s );

  fprintf ( 1, '\n' );
  fprintf ( 1, '     I      R(I)        S(I)        T(I)\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    fprintf ( 1, '  %4d  %10f  %10f  %10f\n', i, r(i), s(i), t(i) );
  end

  return
end


%%%
%> @brief  computes the homogeneous transformation A of the pose vector v
%> @param  v pose vector
%> @return A homogeneous transformation
%> @author Giorgio Grisetti
%%%
function A = v2t(v)
% V2T vector to homogeneous transformation
c = cos(v(3));
s = sin(v(3));
A = [c, -s, v(1);
     s,  c, v(2);
     0   0  1];
end


function [colatitude, longitude, r] = AMICO_Cart2sphere(x, y, z)
	r = sqrt(x.^2 + y.^2 + z.^2);
	longitude  = atan2(y, x);
	colatitude = atan2(sqrt(x.^2 + y.^2), z);
end


function [A,B,D,E,I]=mdds(X)
% gets A, B, D, E & I arrays for magnet driver
N=2;U=3;M=1;Y=1;
A1=zeros(U+N);B2=zeros(U+N,N+M);
%
% X = [R1 R2 R3 C1 C2]
%
R1=X(1);R2=X(2);R3=X(3);C1=X(4);C2=X(5);
%
% V1 V2 V3 iC1 iC2  column labels for A1
% 1  2  3  4	5
%
A1(1,1)=-1/R1;A1(1,4)=-1;A1(1,5)=-1; % From 1st equation
A1(2,1)=1/R2;A1(2,2)=-1/R2;A1(2,4)=-1; % 2nd equation
A1(3,3)=1;A1(3,4)=-R3;A1(3,5)=-R3; % V3 - iC1*R3 - iC2*R3 = 0
A1(4,2)=1;A1(4,3)=-1; % V2 - V3 = E1
A1(5,1)=1;A1(5,3)=-1; % V1 - V3 = E2
%
E1=1;E2=1;Ein=1;
% E1  E2   Ein  Column labels for B2
%  1   2    3
B2(4,1)=E1;
B2(5,2)=E2;
B2(1,3)=-Ein/R1;
%
P=diag([C1 C2]);
%
% Template statements (same for every circuit):
V=A1\B2;H=V(U+1:U+N,1:N+M);I=eye(N);
AB=P\H;A=AB(1:N,1:N);B=AB(1:N,N+1:N+M);
D=V(Y:Y,1:N);E=V(Y:Y,N+1:N+M);


function order_num = tetrahedron_ncc_order_num ( rule )

%*****************************************************************************80
%
%% TETRAHEDRON_NCC_ORDER_NUM returns the order of an NCC rule for the tetrahedron.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Peter Silvester,
%    Symmetric Quadrature Formulae for Simplexes,
%    Mathematics of Computation,
%    Volume 24, Number 109, January 1970, pages 95-100.
%
%  Parameters:
%
%    Input, integer RULE, the index of the rule.
%
%    Output, integer ORDER_NUM, the order (number of points) of the rule.
%
  suborder_num = tetrahedron_ncc_suborder_num ( rule );

  suborder(1:suborder_num) = tetrahedron_ncc_suborder ( rule, suborder_num );

  order_num = sum ( suborder(1:suborder_num) );

  return
end


%TEST_SmoothAbs
%
% This script plots the output of SmoothAbs for a few values of alpha, over
% the domain [-1,1]
%
% Written by Matthew Kelly
% October 2013
% Cornell University
%

t = linspace(-1,1,1000);
alpha = [0.02,0.1,0.5];
N=length(alpha);

figure(104); clf; hold on;
for i=1:N
    x1 = SmoothAbs(t,alpha(i));

    subplot(N,1,i); hold on;
    plot(t,x1,'b-','LineWidth',2)
    plot(t,abs(t),'k:')
    title(['Alpha = ' num2str(alpha(i))],'FontSize',14);
end


%GETDERIVKERNELS  Returns filter coefficients for computing spatial image derivatives
%
%     [kx, ky] = cv.getDerivKernels('OptionName', optionValue, ...)
%
% ## Output
% * __kx__ Output matrix of row filter coefficients. It has the type `KType`.
% * __ky__ Output matrix of column filter coefficients. It has the type
%   `KType`.
%
% ## Options
% * __Dx__ Derivative order in respect of x. default 1
% * __Dy__ Derivative order in respect of y. default 1
% * __KSize__ Aperture size. It can be 'Scharr', 1, 3, 5, or 7. default 3.
% * __Normalize__ Flag indicating whether to normalize (scale down) the filter
%   coefficients or not. Theoretically, the coefficients should have the
%   `denominator = 2^(KSize*2-Dx-Dy-2)`. If you are going to filter
%   floating-point images, you are likely to use the normalized kernels. But
%   if you compute derivatives of an 8-bit image, store the results in a
%   16-bit image, and wish to preserve all the fractional bits, you may want
%   to set `Normalize=false`. default false
% * __KType__ Type of filter coefficients. It can be `single` or `double`.
%   default `single`
%
% The function computes and returns the filter coefficients for spatial image
% derivatives. When `KSize='Scharr'`, the Scharr 3x3 kernels are generated
% (see cv.Scharr). Otherwise, Sobel kernels are generated (see cv.Sobel). The
% filters are normally passed to cv.sepFilter2D.
%
% See also: cv.sepFilter2D, cv.getDerivKernels, cv.getStructuringElement
%


% M-File showing that the RA method of creating the A & B arrays
% gives the same results using the conventional method.
% File:  c:\M_files\short_updates\Matlab_Files\RAconvention.m
% 02/16/07
% See Word file UsingGarray1.doc for background explanations.
clear;clc;
% unit suffixes
u=1e-6;K=1e3;m=1e-3;u=1e-6;p=1e-12;
% component values
R1=5*K;R2=1*K;R3=10*K;
C1=0.1*u;C2=400*p;
Ein=1; % Unity input for (normalized) transfer function
%
% Form W, Q, S, and P arrays:
%
W=[1+R3/R1 1+R3/R1;R2 0];Q=[0 -1/R1;-1 1];S=[Ein/R1;0];P=diag([C1 C2]);
%
% Get A & B arrays using RA method:
%
C=inv(W*P);A=C*Q;B=C*S;
% Display A & B in Command window:
disp('RA Method')
disp(' ')
A
B
disp(' ')
% Using conventional method:
%
disp('Conventional method')
disp(' ')
A=[-1/(R2*C1) 1/(R2*C1);1/(R2*C2) (1/(R1+R3)+1/R2)/C2]
B=[0;(1/(R1+R3))/C2]
%


function [q]=zn2fpd(input)
% [q]=zn2fpd(input)
% Ziegler-Nichols controller for 2nd order processes
% This function computes parameters of the controller (q0, q1, q2, q3, q4).
% Controller is based on forward rectangular method of discretization
% replacing derivation by a four-point difference.
% Transfer function of the controller is as follows:
%
%            q0 + q1*z^-1 + q2*z^-2 + q3*z^-3 + q4*z^-4
% G(z^-1) = --------------------------------------------
%                           1 - z^-1
%
% Transfer function of the controlled system is:
%
%               b1*z^-1 + b2*z^-2
% Gs(z^-1) = -----------------------
%             1 + a1*z^-1 + a2*z^-2
%
% Input: input ... input parameters
%                  input(1) ... a1
%                  input(2) ... b1
%                  input(3) ... a2
%                  input(4) ... b2
%                  input(5) ... sample time T0
% Output: qp ... controller parameters
%                qp(1) ... q0
%                qp(2) ... q1
%                qp(3) ... q2
%                qp(4) ... p1
%                qp(5) ... p2

a1 = input(1);
b1 = input(2);
a2 = input(3);
b2 = input(4);
T0 = input(5);

% compute ultimate gain and frequency
[Kpu, Tu] =  ultim([b1 b2],[a1 a2],T0);

Kp = 0.6*Kpu;
Ti = Tu/2;
Td = Tu/8;

q0 = Kp*(1 + T0/Ti + Td/(6*T0));
q1 = Kp*(-1 + Td/(3*T0));
q2 = Kp*(-Td/T0);
q3 = Kp*(Td/(3*T0));
q4 = Kp*(Td/(6*T0));

q=[q0;q1;q2;q3;q4];


%GENDATH Generation of Highleyman classes
%
%   A = GENDATH(N,LABTYPE)
%
% INPUT
%  N        Number of objects (optional; default: [50,50])
%  LABTYPE  Label type (optional; default: 'crisp')
%
% OUTPUT
%  A        Generated dataset
%
% DESCRIPTION
% Generation of a 2-dimensional 2-class dataset A of N objects
% according to Highleyman.
%
% The two Highleyman classes are defined by
% 1: Gauss([1 1],[1 0; 0 0.25]).
% 2: Gauss([2 0],[0.01 0; 0 4]).
% Class priors are P(1) = P(2) = 0.5
%
% If N is a vector of sizes, exactly N(I) objects are generated
% for class I, I = 1,2.
%
% LABTYPE defines the desired label type: 'crisp' or 'soft'. In the
% latter case true posterior probabilities are set for the labels.
%
% Defaults: N = [50,50], LABTYPE = 'crisp'.
%
% EXAMPLES
% PREX_PLOTC, PREX_CLEVAL
%
% SEE ALSO (PRTools Guide)
% DATASETS, GAUSS, PRDATASETS

% Copyright: R.P.W. Duin, duin@ph.tn.tudelft.nl
% Faculty of Applied Sciences, Delft University of Technology
% P.O. Box 5046, 2600 GA Delft, The Netherlands

% $Id: gendath.m,v 1.5 2009/01/27 13:01:42 duin Exp $

function A = gendath(N,labtype)

	if nargin < 1, N = [50, 50]; end
	if nargin < 2, labtype = 'crisp'; end

	GA = [1 0; 0 0.25];
	GB = [0.01 0; 0 4];
	G = cat(3,GA,GB);
	p = [0.5 0.5];
	N = genclass(N,p);
	U = prdataset([1 1; 2 0],[1 2]','prior',p);
	U = setprior(U,p);
	A = gendatgauss(N,U,G);
	A = setname(A,'Highleyman Dataset');

	switch labtype
	 case 'crisp'
	  ;
	 case 'soft'
	  W = nbayesc(U,cat(3,GA,GB));
	  targets = A*W*classc;
	  A = setlabtype(A,'soft',targets);
	 otherwise
	  error(['Label type ' labtype ' not supported'])
	end

	return


function [EC,ec,degij] = edge_nei_overlap_bd(CIJ)
%EDGE_NEI_OVERLAP_BD     overlap amongst neighbors of two adjacent nodes
%
%   [EC,ec,degij] = edge_nei_bd(CIJ);
%
%   This function determines the neighbors of two nodes that are linked by
%   an edge, and then computes their overlap.  Connection matrix must be
%   binary and directed.  Entries of 'EC' that are 'inf' indicate that no
%   edge is present.  Entries of 'EC' that are 0 denote "local bridges",
%   i.e. edges that link completely non-overlapping neighborhoods.  Low
%   values of EC indicate edges that are "weak ties".
%
%   If CIJ is weighted, the weights are ignored. Neighbors of a node can be
%   linked by incoming, outgoing, or reciprocal connections.
%
%   Inputs:     CIJ,      directed (binary/weighted) connection matrix
%
%   Outputs:    EC,     edge neighborhood overlap matrix
%               ec,     edge neighborhood overlap per edge, in vector format
%               degij,  degrees of node pairs connected by each edge
%
%   Reference:
%
%       Easley and Kleinberg (2010) Networks, Crowds, and Markets.
%           Cambridge University Press, Chapter 3
%
%   Olaf Sporns, Indiana University, 2012

[ik,jk,ck] = find(CIJ);
lel = length(ck);
N = size(CIJ,1);

[~,~,deg] = degrees_dir(CIJ);

ec = zeros(1,lel);
degij = zeros(2,lel);
for e=1:lel
    neiik = setdiff(union(find(CIJ(ik(e),:)),find(CIJ(:,ik(e))')),[ik(e) jk(e)]);
    neijk = setdiff(union(find(CIJ(jk(e),:)),find(CIJ(:,jk(e))')),[ik(e) jk(e)]);
    ec(e) = length(intersect(neiik,neijk))/length(union(neiik,neijk));
    degij(:,e) = [deg(ik(e)) deg(jk(e))];
end;

ff = find(CIJ);
EC = 1./zeros(N);
EC(ff) = ec;                            %#ok<FNDSB>


function MD = mahalanobis(x,m,P)

% MAHALANOBIS  Mahalanobis distance
%   MD = MAHALANOBIS(X,M,P) computes the Mahalanobis distance from a point
%   X to a Gaussian of mean M and covariance P:
%
%   MD = sqrt((X-M)'*inv(P)*(X-M));
%
%   See also NEES.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

MD = sqrt((x-m)'/P*(x-m));

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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 3 of the License, or
%   (at your option) any later version.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


% test for ti quicunx

name = 'turbulence';
name = 'lena';
n = 256;
M = load_image(name);
M = rescale( crop(M,n) );
Jmax = log2(n)-1;
Jmin = Jmax-5;

% boundary conditions
options.bound = 'per';
options.bound = 'sym';
% vanishing moments
vm = 6;
options.primal_vm = vm;
options.dual_vm = vm;

% transform
disp('Computing forward transform');
MW = perform_quicunx_wavelet_transform_ti(M,Jmin,options);
disp('Computing backward transform');
M1 = perform_quicunx_wavelet_transform_ti(MW,Jmin,options);
disp(['Error=' num2str(norm(M-M1,'fro')/norm(M,'fro')) ' (should be 0).']);

rep = 'results/quincunx/';
if not(exist(rep))
    mkdir(rep);
end

% display dual wavelets
clf;
for j=7:12
    MW = MW*0;
    MW(end/2,end/2,j) = 1;
    M1 = perform_quicunx_wavelet_transform_ti(MW,Jmin,options);
    imageplot(M1, '', 4,3,j);
    % save
    if j>6
        warning off;
%        imwrite(rescale(M1), [rep 'quincunx-wavelet-' num2string_fixeddigit(j,2) '.png'], 'png');
        warning on;
        clf;
        surf(M1);
        shading interp; colormap jet(256)
        view(-20,50); axis tight; axis off;
        camlight;
        saveas(gcf, [rep 'quincunx-wavelet-vm' num2str(vm) '-' num2string_fixeddigit(j,2) '.png'], 'png');
    end
end


function [x, funVal, ValueL]=LeastR(A, y, z, opts)
%
%%
% Function LeastR
%      Least Squares Loss with the L1-norm Regularization
%
%% Problem
%
%  min  1/2 || A x - y||^2 + 1/2 rsL2 * ||x||_2^2 + z * ||x||_1
%
%  By default, rsL2=0.
%  When rsL2 is nonzero, this corresponds to the well-know elastic net.
%
%% Input parameters:
%
%  A-         Matrix of size m x n
%                A can be a dense matrix
%                         a sparse matrix
%                         or a DCT matrix
%  y -        Response vector (of size mx1)
%  z -        L_1 norm regularization parameter (z >=0)
%  opts-      Optional inputs (default value: opts=[])
%
%% Output parameters:
%  x-         Solution
%  funVal-    Function value during iterations
%
%% Copyright (C) 2009-2010 Jun Liu, and Jieping Ye
%
% You are suggested to first read the Manual.
%
% For any problem, please contact with Jun Liu via j.liu@asu.edu
%
% Last modified on February 18, 2010.
%
%% Related papers
%
% [1]  Jun Liu and Jieping Ye, Efficient Euclidean Projections
%      in Linear Time, ICML 2009.
%
% [2]  Jun Liu and Jieping Ye, Sparse Learning with Efficient Euclidean
%      Projections onto the L1 Ball, Technical Report ASU, 2008.
%
%% Related functions
%
%  sll_opts, initFactor, pathSolutionLeast
%  LeastC, nnLeastR, nnLeastC,
%
%%

%% Verify and initialize the parameters
%%

% Verify the number of input parameters
if (nargin <3)
    error('\n Inputs: A, y and z should be specified!\n');
elseif (nargin==3)
    opts=[];
end

% Get the size of the matrix A
[m,n]=size(A);% m -- sample size,n -- feature dimension%******************************

% Verify the length of y
%if(size(y,1) ~=m)%********************************
if (length(y) ~=m)
    error('\n Check the length of y!\n');
end

% Verify the value of z
if (z<0)
    error('\n z should be nonnegative!\n');
end

% run sll_opts to set default values (flags)
opts=sll_opts(opts);

%% Detailed initialization
%% Normalization

% Please refer to sll_opts for the definitions of mu, nu and nFlag
%
% If .nFlag =1, the input matrix A is normalized to
%                     A= ( A- repmat(mu, m,1) ) * diag(nu)^{-1}
%
% If .nFlag =2, the input matrix A is normalized to
%                     A= diag(nu)^{-1} * ( A- repmat(mu, m,1) )
%
% Such normalization is done implicitly
%     This implicit normalization is suggested for the sparse matrix
%                                    but not for the dense matrix
%

if (opts.nFlag~=0)
    if (isfield(opts,'mu'))
        mu=opts.mu;
        if(size(mu,2)~=n)
            error('\n Check the input .mu');
        end
    else
        mu=mean(A,1);
    end

    if (opts.nFlag==1)
        if (isfield(opts,'nu'))
            nu=opts.nu;
            if(size(nu,1)~=n)
                error('\n Check the input .nu!');
            end
        else
            nu=(sum(A.^2,1)/m).^(0.5); nu=nu';
        end
    else % .nFlag=2
        if (isfield(opts,'nu'))
            nu=opts.nu;
            if(size(nu,1)~=m)
                error('\n Check the input .nu!');
            end
        else
            nu=(sum(A.^2,2)/n).^(0.5);
        end
    end

    ind_zero=find(abs(nu)<= 1e-10);    nu(ind_zero)=1;
    % If some values in nu is typically small, it might be that,
    % the entries in a given row or column in A are all close to zero.
    % For numerical stability, we set the corresponding value to 1.
end

if (~issparse(A)) && (opts.nFlag~=0)
    fprintf('\n -----------------------------------------------------');
    fprintf('\n The data is not sparse or not stored in sparse format');
    fprintf('\n The code still works.');
    fprintf('\n But we suggest you to normalize the data directly,');
    fprintf('\n for achieving better efficiency.');
    fprintf('\n -----------------------------------------------------');
end

%% Starting point initialization

% compute AT y
if (opts.nFlag==0)
    ATy=A'*y; %A-->mxn;y-->mxk****************************
elseif (opts.nFlag==1)
    ATy=A'*y - sum(y) * mu';  ATy=ATy./nu;
else
    invNu=y./nu;              ATy=A'*invNu-sum(invNu)*mu';
end

% process the regularization parameter

% L2 norm regularization
if isfield(opts,'rsL2')
    rsL2=opts.rsL2;
    if (rsL2<0)
        error('\n opts.rsL2 should be nonnegative!');
    end
else
    rsL2=0;
end

% L1 norm regularization
if (opts.rFlag==0)
    lambda=z;
else % z here is the scaling factor lying in [0,1]
    if (z<0 || z>1)
        error('\n opts.rFlag=1, and z should be in [0,1]');
    end

    lambda_max=max(abs(ATy));
    lambda=z*lambda_max;

    rsL2=rsL2*lambda_max; % the input rsL2 is a ratio of lambda_max
end

% initialize a starting point
if opts.init==2
    %x=zeros(n,k);%*************************************
    x=zeros(n,1);
else
    if isfield(opts,'x0')
        x=opts.x0;
        if (length(x)~=n)
            error('\n Check the input .x0');
        end
    else
        x=ATy;  % if .x0 is not specified, we use ratio*ATy,
        % where ratio is a positive value
    end
end

% compute A x
if (opts.nFlag==0)
    Ax=A* x;
elseif (opts.nFlag==1)
    invNu=x./nu; mu_invNu=mu * invNu;
    Ax=A*invNu -repmat(mu_invNu, m, 1);
else
    Ax=A*x-repmat(mu*x, m, 1);     Ax=Ax./nu;
end

if (opts.init==0) % If .init=0, we set x=ratio*x by "initFactor"
    % Please refer to the function initFactor for detail

    x_norm=sum(abs(x)); x_2norm=x'*x;%*****************************corresponding to L1norm,Fnorm
    if x_norm>=1e-6
        ratio=initFactor(x_norm, Ax, y, lambda,'LeastR', rsL2, x_2norm);
        x=ratio*x;    Ax=ratio*Ax;
    end
end

%% The main program

%% The Armijo Goldstein line search scheme + accelearted gradient descent
if (opts.mFlag==0 && opts.lFlag==0)

    bFlag=0; % this flag tests whether the gradient step only changes a little

    L=1 + rsL2;
    % We assume that the maximum eigenvalue of A'A is over 1

    % assign xp with x, and Axp with Ax
    xp=x; Axp=Ax; xxp=zeros(n,1);

    % alphap and alpha are used for computing the weight in forming search point
    alphap=0; alpha=1;

    for iterStep=1:opts.maxIter
        % --------------------------- step 1 ---------------------------
        % compute search point s based on xp and x (with beta)
        beta=(alphap-1)/alpha;    s=x + beta* xxp;

        % --------------------------- step 2 ---------------------------
        % line search for L and compute the new approximate solution x

        % compute the gradient (g) at s
        As=Ax + beta* (Ax-Axp);

        % compute AT As
        if (opts.nFlag==0)
            ATAs=A'*As;
        elseif (opts.nFlag==1)
            ATAs=A'*As - sum(As) * mu';  ATAs=ATAs./nu;
        else
            invNu=As./nu;                ATAs=A'*invNu-sum(invNu)*mu';
        end

        % obtain the gradient g
        g=ATAs-ATy + rsL2 * s;%************************** +rsL2*s*inv(sigma)

        % copy x and Ax to xp and Axp
        xp=x;    Axp=Ax;

        while (1)
            % let s walk in a step in the antigradient of s to get v
            % and then do the l1-norm regularized projection
            v=s-g/L;

            % L1-norm regularized projection
            x=sign(v).*max(abs(v)-lambda / L,0);

            v=x-s;  % the difference between the new approximate solution x
            % and the search point s

            % compute A x
            if (opts.nFlag==0)
                Ax=A* x;
            elseif (opts.nFlag==1)
                invNu=x./nu; mu_invNu=mu * invNu;
                Ax=A*invNu -repmat(mu_invNu, m, 1);
            else
                Ax=A*x-repmat(mu*x, m, 1);     Ax=Ax./nu;
            end

            Av=Ax -As;
            r_sum=v'*v; l_sum=Av'*Av;

            if (r_sum <=1e-20)
                bFlag=1; % this shows that, the gradient step makes little improvement
                break;
            end

            % the condition is ||Av||_2^2 <= (L - rsL2) * ||v||_2^2
            if(l_sum <= r_sum * (L-rsL2))
                break;
            else
                L=max(2*L, l_sum/r_sum + rsL2);
                % fprintf('\n L=%5.6f',L);
            end
        end

        ValueL(iterStep)=L;

        % --------------------------- step 3 ---------------------------
        % update alpha and alphap, and check whether converge
        alphap=alpha; alpha= (1+ sqrt(4*alpha*alpha +1))/2;

        xxp=x-xp;   Axy=Ax-y;
        funVal(iterStep)=Axy'* Axy/2 + rsL2/2 * x'*x + sum(abs(x)) * lambda;

        if (bFlag)
            % fprintf('\n The program terminates as the gradient step changes the solution very small.');
            break;
        end

        switch(opts.tFlag)
            case 0
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <= opts.tol)
                        break;
                    end
                end
            case 1
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <=...
                            opts.tol* funVal(iterStep-1))
                        break;
                    end
                end
            case 2
                if ( funVal(iterStep)<= opts.tol)
                    break;
                end
            case 3
                norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol)
                    break;
                end
            case 4
                norm_xp=sqrt(xp'*xp);    norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol * max(norm_xp,1))
                    break;
                end
            case 5
                if iterStep>=opts.maxIter
                    break;
                end
        end
    end
end

%% Reformulated problem + Nemirovski's scheme

% .mFlag=1, and .lFlag=0
%  refomulate the problem as the constrained convex optimization
%  problem, and then apply Armijo Goldstein line search scheme

% Problem:
%    min  1/2 || A x - y||^2 + 1/2 rsL2 * ||x||_2^2 + z * t' * 1
%    s.t.   |x| <= t

if(opts.mFlag==1 && opts.lFlag==0)

    bFlag=0; % this flag tests whether the gradient step only changes a little

    L=1 + rsL2;
    % We assume that the maximum eigenvalue of A'A is over 1

    % assign xp with x, and Axp with Ax
    xp=x; Axp=Ax; xxp=zeros(n,1);
    t=abs(x); tp=t;
    % t is the upper bound of absolute value of x

    % alphap and alpha are used for computing the weight in forming search point
    alphap=0; alpha=1;

    for iterStep=1:opts.maxIter
        % --------------------------- step 1 ---------------------------
        % compute search point s based on xp and x (with beta)
        beta=(alphap-1)/alpha;    s=x + beta* xxp; s_t= t + beta * (t -tp);

        % --------------------------- step 2 ---------------------------
        % line search for L and compute the new approximate solution x

        % compute the gradient (g) at s
        As=Ax + beta* (Ax-Axp);

        % compute AT As
        if (opts.nFlag==0)
            ATAs=A'*As;
        elseif (opts.nFlag==1)
            ATAs=A'*As - sum(As) * mu';  ATAs=ATAs./nu;
        else
            invNu=As./nu;                ATAs=A'*invNu-sum(invNu)*mu';
        end

        % obtain the gradient g
        g=ATAs-ATy + rsL2 * s;

        % copy x and Ax to xp and Axp
        xp=x;    Axp=Ax;
        tp=t;

        while (1)
            % let s walk in a step in the antigradient of s to get v
            % and then do the l1-norm regularized projection

            u=s-g/L;
            v= s_t - lambda / L;

            % projection
            [x, t]=ep1R(u, v, n);

            v=x-s;  % the difference between the new approximate solution x
                       % and the search point s

            v_t=t-s_t;

            % compute A x
            if (opts.nFlag==0)
                Ax=A* x;
            elseif (opts.nFlag==1)
                invNu=x./nu; mu_invNu=mu * invNu;
                Ax=A*invNu -repmat(mu_invNu, m, 1);
            else
                Ax=A*x-repmat(mu*x, m, 1);     Ax=Ax./nu;
            end

            Av=Ax -As;
            r_sum=v'*v + v_t'*v_t; l_sum=Av'*Av + v'*v * rsL2;

            if (r_sum <=1e-20)
                bFlag=1; % this shows that, the gradient step makes little improvement
                break;
            end

            % the condition is ||Av||_2^2 + rsL2 * ||v||_2^2
            %                       <= L * (||v||_2^2 + ||v_t|| _2^2 )
            if(l_sum <= r_sum * L)
                break;
            else
                L=max(2*L, l_sum/r_sum);
                % fprintf('\n L=%5.6f',L);
            end
        end

        ValueL(iterStep)=L;

        % --------------------------- step 3 ---------------------------
        % update alpha and alphap, and check whether converge
        alphap=alpha; alpha= (1+ sqrt(4*alpha*alpha +1))/2;

        xxp=x-xp;   Axy=Ax-y;
        funVal(iterStep)=Axy'* Axy/2 + rsL2/2 * x'*x + sum(t) * lambda;

        if (bFlag)
            % fprintf('\n The program terminates as the gradient step changes the solution very small.');
            break;
        end

        switch(opts.tFlag)
            case 0
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <= opts.tol)
                        break;
                    end
                end
            case 1
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <=...
                            opts.tol* funVal(iterStep-1))
                        break;
                    end
                end
            case 2
                if ( funVal(iterStep)<= opts.tol)
                    break;
                end
            case 3
                norm_xxp=sqrt(xxp'*xxp + norm(t-tp)^2);
                if ( norm_xxp <=opts.tol)
                    break;
                end
            case 4
                norm_xp=sqrt(xp'*xp + tp'*tp);    norm_xxp=sqrt(xxp'*xxp+ norm(t-tp)^2);
                if ( norm_xxp <=opts.tol * max(norm_xp,1))
                    break;
                end
            case 5
                if iterStep>=opts.maxIter
                    break;
                end
        end
    end

end

%% adaptive line search

% .mFlag=1, and .lFlag=1
%  refomulate the problem as the constrained convex optimization
%  problem, and then apply adaptive line search scheme

% Problem:
%    min  1/2 || A x - y||^2 + 1/2 rsL2 * ||x||_2^2 + z * t' * 1
%    s.t.   |x| <= t

if(opts.mFlag==1 && opts.lFlag==1)

    bFlag=0; % this flag tests whether the gradient step only changes a little

    L=1 + rsL2;
    % We assume that the maximum eigenvalue of A'A is over 1

    gamma=1;
    % we shall set the value of gamma = L,
    % where L is appropriate for the starting point

    xp=x; Axp=Ax;
    % store x and Ax
    xxp=zeros(n,1);
    % the difference of x and xp
    t=abs(x); tp=t;
    % t is the upper bound of absolute value of x

    % compute AT Ax
    if (opts.nFlag==0)
        ATAx=A'*Ax;
    elseif (opts.nFlag==1)
        ATAx=A'*Ax - sum(Ax) * mu';  ATAx=ATAx./nu;
    else
        invNu=Ax./nu;                ATAx=A'*invNu-sum(invNu)*mu';
    end

    % We begin the adaptive line search in the following
    %
    % Note that, in the line search, L and beta are changing

    for iterStep=1:opts.maxIter

        ATAxp=ATAx;
        % store ATAx to ATAxp

        if (iterStep~=1)
            % compute AT Ax
            if (opts.nFlag==0)
                ATAx=A'*Ax;
            elseif (opts.nFlag==1)
                ATAx=A'*Ax - sum(Ax) * mu';  ATAx=ATAx./nu;
            else
                invNu=Ax./nu;                ATAx=A'*invNu-sum(invNu)*mu';
            end
        end

        %--------- Line Search for L begins
        while (1)
            if (iterStep~=1)
                alpha= (-gamma+ sqrt(gamma*gamma + 4* L * gamma)) / (2*L);
                beta= (gamma - gamma* alphap) / (alphap * gamma + alphap* L * alpha);
                % beta is the coefficient for generating search point s

                s=x + beta* xxp;   s_t= t + beta * (t -tp);
                As=Ax + beta* (Ax-Axp);
                ATAs=ATAx + beta * (ATAx- ATAxp);
                % compute the search point s, A * s, and A' * A * s
            else
                alpha= (-1+ sqrt(5)) / 2;
                beta=0; s=x; s_t=t; As=Ax; ATAs=ATAx;
            end

            g=ATAs-ATy + rsL2 * s;
            % compute the gradient g

            % let s walk in a step in the antigradient of s
            u=s-g/L;
            v= s_t - lambda / L;

            % projection
            [xnew, tnew]=ep1R(u,v,n);

            v=xnew-s;  % the difference between the new approximate solution x
                            % and the search point s
            v_t=tnew-s_t;

            % compute A xnew
            if (opts.nFlag==0)
                Axnew=A* xnew;
            elseif (opts.nFlag==1)
                invNu=xnew./nu; mu_invNu=mu * invNu;
                Axnew=A*invNu -repmat(mu_invNu, m, 1);
            else
                Axnew=A*xnew-repmat(mu*xnew, m, 1);     Axnew=Axnew./nu;
            end

            Av=Axnew -As;
            r_sum=v'*v + v_t'*v_t; l_sum=Av'*Av + v'*v * rsL2;

            if (r_sum <=1e-20)
                bFlag=1; % this shows that, the gradient step makes little improvement
                break;
            end

            % the condition is ||Av||_2^2 + rsL2 * ||v||_2^2
            %                       <= L * (||v||_2^2 + ||v_t|| _2^2 )
            if(l_sum <= r_sum * L)
                break;
            else
                L=max(2*L, l_sum/r_sum);
                % fprintf('\n L=%5.6f',L);
            end
        end
        %--------- Line Search for L ends

        gamma=L* alpha* alpha;    alphap=alpha;
        % update gamma, and alphap

        ValueL(iterStep)=L;

        tao=L * r_sum / l_sum;
        if (tao >=5)
            L=L*0.8;
        end
        % decrease the value of L

        xp=x;    x=xnew; xxp=x-xp;
        Axp=Ax;  Ax=Axnew;
        % update x and Ax with xnew and Axnew
        tp=t; t=tnew;
        % update tp and t

        Axy=Ax-y;
        funVal(iterStep)=Axy' * Axy/2 + rsL2/2 * x'*x + lambda * sum(t);
        % compute function value

        if (bFlag)
            % fprintf('\n The program terminates as the gradient step changes the solution very small.');
            break;
        end

        switch(opts.tFlag)
            case 0
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <= opts.tol)
                        break;
                    end
                end
            case 1
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <=...
                            opts.tol* funVal(iterStep-1))
                        break;
                    end
                end
            case 2
                if ( funVal(iterStep)<= opts.tol)
                    break;
                end
            case 3
                norm_xxp=sqrt(xxp'*xxp+ norm(t-tp)^2);
                if ( norm_xxp <=opts.tol)
                    break;
                end
            case 4
                norm_xp=sqrt(xp'*xp + tp'*tp);    norm_xxp=sqrt(xxp'*xxp+ norm(t-tp)^2);
                if ( norm_xxp <=opts.tol * max(norm_xp,1))
                    break;
                end
            case 5
                if iterStep>=opts.maxIter
                    break;
                end
        end
    end
end

%%
if(opts.mFlag==0 && opts.lFlag==1)
    error('\n The function does not support opts.mFlag=0 & opts.lFlag=1!');
end


% StackExchange Mathematics Q1909139
% https://math.stackexchange.com/questions/1909139
% Projection of a Symmetric Matrix onto the Probability Simplex
% References:
%   1.
% Remarks:
%   1.  B
% TODO:
% 	1.  C
% Release Notes
% - 1.0.000     17/06/2021
%   *   First release.

%% General Parameters

subStreamNumberDefault = 79;

run('InitScript.m');

figureIdx           = 0;
figureCounterSpec   = '%04d';

generateFigures = ON;

%% Simulation Parameters

numRows = 4;

%% Generate Data

mY = randn(numRows, numRows);
% mY = mY + mY.';

vI = zeros(numRows * numRows, 1);
vI(1:(numRows + 1):(numRows ^ 2)) = 1;

hObjFun = @(mX) 0.5 * sum((mX(:) - mY(:)) .^ 2);

%% Solution by CVX

solverString = 'CVX';

% cvx_solver('SDPT3'); %<! Default, Keep numRows low
% cvx_solver('SeDuMi');
% cvx_solver('Mosek'); %<! Can handle numRows > 500, Very Good!
% cvx_solver('Gurobi');

hRunTime = tic();

cvx_begin('quiet')
    % cvx_precision('best');
    variable mX(numRows, numRows) symmetric;
    minimize( (0.5 * sum_square(mX(:) - mY(:))) );
    subject to
        % mX <In> symmetric(numRows); %<! Doesn't work for some reason
        trace(mX) == 1;
        mX >= 0;
cvx_end

runTime = toc(hRunTime);

DisplayRunSummary(solverString, hObjFun, mX, runTime, cvx_status);

sCvxSol.vXCvx     = mX(:);
sCvxSol.cvxOptVal = hObjFun(mX);

%% Solution by Orthogonal Projection onto the Intersection of Convex Sets

hP1 = @(vX) reshape((reshape(vX, numRows, numRows) + reshape(vX, numRows, numRows).') / 2, 1, numRows * numRows);
hP2 = @(vX) max(vX, 0); %<! Projection mX >= 0
hP3 = @(vX) (vX .* ~vI) + ((vX - ((sum(vX .* vI) - 1) / numRows)) .* vI); %<! Projection trace(mX) == 1

hRunTime = tic();
vX = OrthogonalProjectionOntoConvexSets({hP1; hP2; hP3}, mY(:), 100, 1e-6);
runTime = toc(hRunTime);

mX1 = reshape(vX, numRows, numRows);

DisplayRunSummary(solverString, hObjFun, reshape(vX, numRows, numRows), runTime);

%% Restore Defaults

% set(0, 'DefaultFigureWindowStyle', 'normal');
% set(0, 'DefaultAxesLooseInset', defaultLoosInset);


function K = covCos(hyp, x, z, i)

% Stationary covariance function for a sinusoid with period p in 1d:
%
% k(x,z) = sf^2*cos(2*pi*(x-z)/p)
%
% where the hyperparameters are:
%
% hyp = [ log(p)
%         log(sf) ]
%
% Note that covPeriodicNoDC converges to covCos as ell goes to infinity.
%
% Copyright (c) by James Robert Lloyd, 2013-08-05.
%
% See also COVFUNCTIONS.M, COVPERIODICNODC.M.

if nargin<2, K = '2'; return; end                  % report number of parameters
if nargin<3, z = []; end                                   % make sure, z exists
xeqz = isempty(z); dg = strcmp(z,'diag');                       % determine mode

[n,D] = size(x);
if D>1, error('Covariance is defined for 1d data only.'), end
p   = exp(hyp(1));
sf2 = exp(2*hyp(2));

% precompute distances
if dg                                                               % vector kxx
  K = zeros(size(x,1),1);
else
  if xeqz                                                 % symmetric matrix Kxx
    K = repmat(x,1,n) - repmat(x',n,1);
  else                                                   % cross covariances Kxz
    K = repmat(x,1,size(z,1)) - repmat(z',n,1);
  end
end

K = 2*pi*K/p;
if nargin<4                                                        % covariances
    K = sf2*cos(K);
else                                                               % derivatives
  if i==1
    K = sf2*sin(K).*K;
  elseif i==2
    K = 2*sf2*cos(K);
  else
    error('Unknown hyperparameter')
  end
end


function R = ProjectToSO3(mat)
% *** CHAPTER 3: RIGID-BODY MOTIONS ***
% Takes mat: A matrix near SO(3) to project to SO(3).
% Returns R representing the closest rotation matrix that is in SO(3).
% This function uses singular-value decomposition (see
% http://hades.mech.northwestern.edu/index.php/Modern_Robotics_Linear_Algebra_Review)
% and is only appropriate for matrices close to SO(3).
% Example Inputs:
%
% clear; clc;
% mat = [ 0.675, 0.150,  0.720;
%         0.370, 0.771, -0.511;
%        -0.630, 0.619,  0.472];
% R = ProjectToSO3(mat)
%
% Output:
% R =
%    0.6790    0.1489    0.7189
%    0.3732    0.7732   -0.5127
%   -0.6322    0.6164    0.4694

[U, S, V] = svd(mat);
R = U * V';
if det(R) < 0
    % In this case the result may be far from mat.
    R = [R(:, 1: 2); -R(:, 3)];
end
end


% Compute the frequency range of the mel filterbank
% Inputs:
%   start_freq:     the lowerest linear frequency included in the calculation
%   linear_samp:    sampling frequency
%   N_mel:          number of mel banks used
% Output:
%   bin_lower_edge:    the lower edge linear frequency of each mel bank
%   bin_upper_edge:    the upper edge linear frequency of each mel bank

function [bin_lower_edge, bin_upper_edge] = mel_bank_range(start_freq, linear_samp, N_mel)

% get the mel version of start frequency and linear sampling rate
start_mel = linear2mel(start_freq);
samp_mel = linear2mel(linear_samp/2);

% slow implementation
if 0
    for i=1:N_mel
        % find the lower edge linear frequency of the bank
        tmp_mel = (i-1)*(samp_mel-start_mel) / (N_mel+1);
        bin_lower_edge(i) = mel2linear(tmp_mel+start_mel);
        % find the upper edge linear frequency of the bank
        tmp_mel = (i+1)*(samp_mel-start_mel) / (N_mel+1);
        bin_upper_edge(i) =  mel2linear(tmp_mel+start_mel);
    end
else
    % fast implementation
    i=1:N_mel;
    % find the lower edge linear frequency of the bank
    tmp_mel = (i-1)*(samp_mel-start_mel) / (N_mel+1);
    bin_lower_edge = mel2linear(tmp_mel+start_mel);
    % find the upper edge linear frequency of the bank
    tmp_mel = (i+1)*(samp_mel-start_mel) / (N_mel+1);
    bin_upper_edge =  mel2linear(tmp_mel+start_mel);
end


function r = dirrand(m,n)
% DIRRAND - Uniform Dirichlet random vectors
%
%    R = DIRRAND(M) returns vector of length M chosen from
%    Dirichlet(1,...,1) distribution.
%    R = DIRRAND(M,N) returns N such vectors in MxN matrix.
%
%   References: Gelman, Carlin, Stern, Dunson, Vehtari & Rubin (2013),
%               Bayesian Data Analysis, third edition, p. 583.
%
% Copyright (c) 1998-2004 Aki Vehtari

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

if nargin < 2
  n=1;
end

% Generate random numbers from Gamma(1,1) distribution...
r=rand(m,n);
r=-reallog(r);
% ...and scale sum to unity
rs=sum(r);
for i1=1:m
  r(i1,:)=r(i1,:)./rs;
end


%% doubleContraction
% Below is a demonstration of the features of the |doubleContraction| function

%%
clear; close all; clc;

%% Syntax
% |C=doubleContraction(A,B,subContract);|

%% Description
% This function performs a double contraction of two tensors |A| and |B| to
% produce the output tensor |C|. The tensors are either both 3x3 second
% order tensors or |A| is a 4th order 3x3x3x3 tensor. The optional 3rd
% input |subContract| defines the indices to contract over for 4th order
% tensors e.g. |subContract=[1 2]| would contract over the first 2 indices.
%

%% Examples
%

%% Double contraction of a 2nd-order and a 2nd-order tensor

%%
% Creating an example tensor. Here a tensor |A| with all zeros except for
% the 3,3 component is created. Next a tensor |B| which, through double
% contraction, can "pick out" this scalar value is created. Finally the
% double contraction is performed illustrating this process.

%Create example tensor A
A=zeros(3,3); A(3,3)=pi; %Zeros with Azz=A33=pi
R=euler2DCM([0.25*pi 0.25*pi 0]); %Rotation matrix
A=R*A*R' %Rotated version of A

% Create 'structure' tensor example B
b=[0 0 1]*R.'; %Rotated Z vector
B=b.'*b %Rotated "structure" tensor for vector b

%%
% Double contraction using |doubleContraction|
s=doubleContraction(A,B)

%% Double contraction of a 4th-order and a 2nd-order tensor

%%
% Example for Hooke's law of linear elasticity

%Creating the 4th order linear elastic stiffness tensor
I=eye(3,3); %The 2nd order identity tensor
II1=dyadicProduct(I,I,1); %4th order base tensor 1
II3=dyadicProduct(I,I,3); %4th order base tensor 3

%Parameters for Hooke's law
mu=1; %The shear modulus
lambda=5; %The lambda lame parameter

%Compose stiffness tensor
C=lambda.*II1+2.*mu.*II3;

%Create strain tensor
E=rand(3,3); E=E*E'

%%
% Double contraction using |doubleContraction|
subContract=[3 4];
S=doubleContraction(C,E,subContract)

%% Using symbolic variables

%%
% Example for Hooke's law of linear elasticity

%Creating the 4th order linear elastic stiffness tensor
I=eye(3,3); %The 2nd order identity tensor
II1=dyadicProduct(I,I,1); %4th order base tensor 1
II3=dyadicProduct(I,I,3); %4th order base tensor 3

%Parameters for Hooke's law
try
    syms mu lambda
catch
    mu=1; %The shear modulus
    lambda=5; %The lambda lame parameter
end
%Compose stiffness tensor
C=lambda.*II1+2.*mu.*II3;

%Display Voigt mapped version
c=voigtMap(C)

%Create strain tensor
syms E1_1 E2_2 E3_3 E1_2 E1_3 E2_3;
E=[E1_1 E1_2 E1_3;...
   E1_2 E2_2 E2_3;...
   E1_3 E2_3 E3_3]

%%
% Double contraction using |doubleContraction|

subContract=[3 4];
S=doubleContraction(C,E,subContract)

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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 3 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, see <http://www.gnu.org/licenses/>.


function c = martin_phase(N)
% phase colormap as found in a tool from Martin Uecker (muecker@gwdg.de)

    if nargin < 1
        N = 64;
    end

phase = linspace(0,2*pi,N);

c = zeros(N,3);
c(:,1) = sin(phase);
c(:,2) = sin(phase + 120 * pi/180);
c(:,3) = sin(phase + 240 * pi/180);

c = (c + 1)/2;

end


% Fast community finding algorithm by M. Newman
% Source: "Fast algorithm for detecting community
%                   structure in networks", Mark Newman
%
% INPUTs: adjacency matrix, nxn
% OUTPUTs: sequential group (cluster) formation,
%          modularity metric for each cluster breakdown
%
% Other functions used: numEdges.m
% Note: To save the plot generated in this routine:
%       uncomment "print newmanCommFast_example.pdf"
%
% GB: last updated, Oct 12 2012

function [groups_hist,Q]=newmanCommFast(adj)

groups={};
groups_hist={};  % a list of groups at each step
Q=[];
n=size(adj,1);   % number of vertices
groups_hist{1}={};

for i=1:n
  groups{i}=i;   % each node starts out as one community
  groups_hist{1}{i}=i;
end

Q(1) = Qfn(groups,adj);

for s=1:n-1 % all possible iterations

  dQ=zeros(length(groups));

  for i=1:length(groups)
    for j=i+1:length(groups)
      group_i=groups{i};
      group_j=groups{j};

      dQ(i,j)=0; % default

      % check if connected
      connected=0;
      if sum(sum(adj([group_i group_j],[group_i group_j])))>sum(sum(adj(group_i,group_i)))+sum(sum(adj(group_j,group_j)))
	connected=1;
      end

      if connected && not(isempty(group_i)) && not(isempty(group_j))
	% join groups i and j?
	dQ(i,j)=deltaQ(groups,adj,i,j);
      end

    end
  end

  % pick max nonzero dQ
  dQ(find(dQ==0))=-Inf;
  [minv,minij]=max(dQ(:));

  [mini,minj]=ind2sub([size(dQ,1),size(dQ,1)],minij);   % i and j corresponding to min dQ
  groups{mini}=sort([groups{mini} groups{minj}]);
  groups{minj}=groups{length(groups)}; % swap minj with last group
  groups=groups(1:length(groups)-1);

  groups_hist{length(groups_hist)+1}=groups; % save current snapshot
  Q(length(Q)+1) = Qfn(groups,adj);

end % end of all iterations

num_modules=[];
for g=1:length(groups_hist)
  num_modules=[num_modules length(groups_hist{g})];
end

set(gcf,'Color',[1 1 1],'Colormap',jet);
plot(num_modules,Q,'ko-')
xlabel('number of modules / communities')
ylabel('modularity metric, Q')

% print newmanCommFast_example.pdf

function dQ=deltaQ(groups,adj,i,j)

% computing the delta Q between two community configurations
% dQ = 2(e_ij - ai*aj) or (Q_groups_(i,j)_merged - Q_original)
% inputs: current community assignments: groups, adjacency matrix, i,j to be joined
% outputs: delta Q value (real number)

% $$$ Q1=Qfn(groups,adj);
% $$$ groups{i}=[groups{i} groups{j}];
% $$$ groups{j}=groups{length(groups)};
% $$$ groups=groups(1:length(groups)-1);
% $$$ Q2=Qfn(groups,adj);
% $$$ dQ = Q2-Q1;

% alternative dQ = 2(e_ij - ai*aj) from paper;
nedges=numEdges(adj); % compute the total number of edges
e_ii = numEdges( adj(groups{i},groups{i}) ) / nedges;
e_jj = numEdges( adj(groups{j},groups{j}) ) / nedges;
e_ij = numEdges( adj([groups{i} groups{j}],[groups{i} groups{j}]) ) / nedges - e_ii - e_jj;

a_i=sum(sum(adj(groups{i},:)))/nedges-e_ii;
a_j=sum(sum(adj(groups{j},:)))/nedges-e_jj;

dQ = 2*(e_ij-a_i*a_j);

function Q=Qfn(modules,adj) % ....... same as modularityMetric.m ........

% Computing the modularity for the final module break-down
% Defined as: Q=sum_over_modules_i (eii-ai^2) (eq 5) in Newman and Girvan.
% eij = fraction of edges that connect community i to community j
% ai=sum_j (eij)

nedges=numEdges(adj); % compute the total number of edges

Q = 0;
for m=1:length(modules)

  e_mm=numEdges(adj(modules{m},modules{m}))/nedges;
  a_m=sum(sum(adj(modules{m},:)))/nedges - e_mm;  % counting e_mm only once

  Q = Q + (e_mm - a_m^2);
end


function [ num_int, pi ] = plane_imp_triangle_int_3d ( a, b, c, d, t )

%*****************************************************************************80
%
%% PLANE_IMP_TRIANGLE_INT_3D: intersection ( implicit plane, triangle ) in 3D.
%
%  Discussion:
%
%    The implicit form of a plane in 3D is:
%
%      A * X + B * Y + C * Z + D = 0
%
%    There may be 0, 1, 2 or 3 points of intersection returned.
%
%    If two intersection points are returned, then the entire line
%    between them comprises points of intersection.
%
%    If three intersection points are returned, then all points of
%    the triangle intersect the plane.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real T(3,3), the vertices of the triangle.
%
%    Input, real A, B, C, D, the implicit plane parameters.
%
%    Output, integer NUM_INT, the number of intersection points returned.
%
%    Output, real PI(3,3), the intersection points.
%
  dim_num = 3;
  num_int = 0;
  pi = [];
%
%  Compute the signed distances between the vertices and the plane.
%
  dist1 = a * t(1,1) + b * t(2,1) + c * t(3,1) + d;
  dist2 = a * t(1,2) + b * t(2,2) + c * t(3,2) + d;
  dist3 = a * t(1,3) + b * t(2,3) + c * t(3,3) + d;
%
%  Consider any zero distances.
%
  if ( dist1 == 0.0 )
    num_int = num_int + 1;
    pi(1:dim_num,num_int) = t(1:dim_num,1);
  end

  if ( dist2 == 0.0 )
    num_int = num_int + 1;
    pi(1:dim_num,num_int) = t(1:dim_num,2);
  end

  if ( dist3 == 0.0 )
    num_int = num_int + 1;
    pi(1:dim_num,num_int) = t(1:dim_num,3);
  end
%
%  If 2 or 3 of the nodes intersect, we're already done.
%
  if ( 2 <= num_int )
    return
  end
%
%  If one node intersects, then we're done unless the other two
%  are of opposite signs.
%
  if ( num_int == 1 )

    if ( dist1 == 0.0 )

      [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,2), t(1:dim_num,3), ...
        dist2, dist3, num_int, pi );

    elseif ( dist2 == 0.0 )

      [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,1), t(1:dim_num,3), ...
        dist1, dist3, num_int, pi );

    elseif ( dist3 == 0.0 )

      [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,1), t(1:dim_num,2), ...
        dist1, dist2, num_int, pi );

    end

    return

  end
%
%  All nodal distances are nonzero, and there is at least one
%  positive and one negative.
%
  if ( dist1 * dist2 < 0.0 & dist1 * dist3 < 0.0 )

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,1), t(1:dim_num,2), ...
      dist1, dist2, num_int, pi );

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,1), t(1:dim_num,3), ...
      dist1, dist3, num_int, pi );

  elseif ( dist2 * dist1 < 0.0 & dist2 * dist3 < 0.0 )

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,2), t(1:dim_num,1), ...
      dist2, dist1, num_int, pi );

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,2), t(1:dim_num,3), ...
      dist2, dist3, num_int, pi );

  elseif ( dist3 * dist1 < 0.0 & dist3 * dist2 < 0.0 )

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,3), t(1:dim_num,1), ...
      dist3, dist1, num_int, pi );

    [ num_int, pi ] = plane_imp_triangle_int_add_3d ( t(1:dim_num,3), t(1:dim_num,2), ...
      dist3, dist2, num_int, pi );

  end

  return
end


%
% Polynomial power  h = f^k
%
% Syntax:  >> h = PolynomialPower(f,k)
%     or   >> h = ppower(f,k)
%
% Input:     f --- (string)  polynomial
%            k --- (integer) exponent
%
% Output:    h --- (string) polynomial f^k if k is nonnegative
%
% Example:   >> PolynomialPower('x*y+1',3)
%
%            ans =
%
%            1 + 3*x*y + 3*x^2*y^2 + x^3*y^3


function x=logistic(n,level,a,x0)
%Syntax: x=logistic(n,level,a,x0)
%________________________________
%
% Simulation of the Quadratic map.
%    x'=ax(1-x)
%
% x is the simulated time series.
% n is the number of the simulated points.
% level is the noise standard deviation divided by the standard deviation of the
%   noise-free time series. We assume Gaussian noise with zero mean.
% a is the parameter.
% x0 is the initial value for x.
%
%
% Reference:
%
% May R M (1976): Simple mathematical modelswith very complicated dynamics.
% Nature 261: 459-467
%
%
% Alexandros Leontitsis
% Department of Education
% University of Ioannina
% 45110 - Dourouti
% Ioannina
% Greece
%
% University e-mail: me00743@cc.uoi.gr
% Lifetime e-mail: leoaleq@yahoo.com
% Homepage: http://www.geocities.com/CapeCanaveral/Lab/1421
%
% 17 Nov 2001

if nargin<1 | isempty(n)==1
    n=500;
else
    % n must be scalar
    if sum(size(n))>2
        error('n must be scalar.');
    end
    % n must be positive
    if n<0
        error('n must be positive.');
    end
    % n must be an integer
    if round(n)-n~=0
        error('n must be an integer.');
    end
end

if nargin<2 | isempty(level)==1
    level=0;
else
    % level must be a scalar
    if sum(size(level))>2
        error('level must be scalar.');
    end
    % level must be positive
    if level<0
        error('level must be positive.');
    end
end

if nargin<3 | isempty(a)==1
    a=4;
else
    % a must be scalar
    if sum(size(a))>2
        error('a must be scalar.');
    end
end

if nargin<4 | isempty(x0)==1
    x0=0.1;
else
    % x0 must be scalar
    if sum(size(x0))>2
        error('x0 must be scalar.');
    end
end

% Initialize
x(1,1)=a*x0*(1-x0);

% Simulate
for i=2:n
    x(i,1)=a*x(i-1,1)*(1-x(i-1,1));
end

% Add normal white noise
x=x+randn(n,1)*level*std(x);


function [gradf, err] = tapas_riddersgradient(f, x, varargin)
% Calculates the gradient of the function f at point x according to Ridders' method:
%
% Ridders, CJF. (1982). Accurate computation of F'(x) and F'(x) F''(x). Advances in Engineering
%     Software, 4(2), 75-6.
%
% INPUT:
%    f             Function handle of a real function of n real variables which are passed as
%                  *one* vector with n elements
%    x             Point at which to differentiate f
%
% OUTPUT:
%    gradf         Gradient of f at x (row vector)
%    err           Error estimates (row vector)
%
% OPTIONS:
%    Optionally, the third argument of the function can be a structure containing further
%    settings for Ridder's method.
%
%    varargin{1}.init_h      Initial finite difference (default: 1)
%    varargin{1}.div         Divisor used to reduce h on each step (default: 1.2)
%    varargin{1}.min_steps   Minimum number of steps in h (default: 3)
%    varargin{1}.max_steps   Maximum number of steps in h (default: 100)
%    varargin{1}.tf          Terminate if last step worse than preceding by a factor of tf
%                            (default: 2)
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2013 Christoph Mathys, TNU, UZH & ETHZ
%
% This file 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/>.

    n = length(x);

    % Defaults
    options.init_h     = 1;
    options.div        = 1.2;
    options.min_steps  = 3;
    options.max_steps  = 100;
    options.tf         = 2;
    gradf              = NaN(1,n);
    err                = NaN(1,n);

    % Overrides
    if nargin > 2
        options_ovr = varargin{1};

        if isfield(options_ovr,'init_h')
            options.init_h = options_ovr.init_h;
        end

        if isfield(options_ovr,'div')
            options.div = options_ovr.div;
        end

        if isfield(options_ovr,'min_steps')
            options.min_steps = options_ovr.min_steps;
        end

        if isfield(options_ovr,'max_steps')
            options.max_steps = options_ovr.max_steps;
        end

        if isfield(options_ovr,'tf')
            options.tf = options_ovr.tf;
        end
    end

    % Check if f and x match
    try
        f(x);
    catch err
        error('tapas:hgf:ridders:CannotEvalFun', 'Function cannot be evaluated at differentiation point.');
    end

    % Loop through argument variables
    for i = 1:n

        % Construct filehandle to be passed to riddersdiff
        fxih = @(xi) fxi(f,x,i,xi);

        % Calculate derivative
        [gradf(i), err(i)] = tapas_riddersdiff(fxih,x(i),options);
    end
end

function fxi = fxi(f,x,i,xi)
    xx    = x;
    xx(i) = xi;
    fxi   = f(xx);
end


function triangle_svg_test01 ( )

%*****************************************************************************80
%
%% TRIANGLE_SVG_TEST01 calls TRIANGLE_SVG to plot a triangle and some points.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 April 2014
%
%  Author:
%
%    John Burkardt
%
  p_num = 13;
  p = [ ...
       0.333333333333333, 0.333333333333333; ...
       0.479308067841923, 0.260345966079038; ...
       0.260345966079038, 0.479308067841923; ...
       0.260345966079038, 0.260345966079038; ...
       0.869739794195568, 0.065130102902216; ...
       0.065130102902216, 0.869739794195568; ...
       0.065130102902216, 0.065130102902216; ...
       0.638444188569809, 0.312865496004875; ...
       0.638444188569809, 0.048690315425316; ...
       0.312865496004875, 0.638444188569809; ...
       0.312865496004875, 0.048690315425316; ...
       0.048690315425316, 0.638444188569809; ...
       0.048690315425316, 0.312865496004875 ]';
  t = [ ...
       0.0, 0.0; ...
       1.0, 0.0; ...
       0.0, 1.0 ]';

  plot_filename = 'test01.svg';

  triangle_svg ( plot_filename, t, p_num, p );

  return
end


function outsig=rampup(L,wintype)
%RAMPUP  Rising ramp function
%   Usage: outsig=rampup(L);
%
%   `rampup(L)` will return a rising ramp function of length *L*. The
%   ramp is a sinusoide starting from zero and ending at one. The ramp
%   is centered such that the first element is always 0 and the last
%   element is not quite 1, such that the ramp fits with following ones.
%
%   `rampup(L,wintype)` will use another window for ramping. This may be any
%   of the window types from |firwin|. Please see the help on |firwin| for
%   more information. The default is to use a piece of the Hann window.
%
%   See also: rampdown, rampsignal, firwin

complainif_argnonotinrange(nargin,1,2,mfilename);

if nargin==1
  wintype='hann';
end;

win=firwin(wintype,2*L,'inf');
outsig=win(L+1:2*L);


function geometry_test1745 ( )

%*****************************************************************************80
%
%% TEST1745 tests R8MAT_SOLVE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2005
%
%  Author:
%
%    John Burkardt
%
  n = 3;
  nrhs = 2;

  a = [ ...
     1.0,  4.0,  7.0; ...
     2.0,  5.0,  8.0; ...
     3.0,  6.0,  0.0; ...
    14.0, 32.0, 23.0; ...
     7.0, 16.0,  7.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST1745\n' );
  fprintf ( 1, '  R8MAT_SOLVE solves linear systems.\n' );
  fprintf ( 1, '\n' );
%
%  Print out the matrix to be inverted.
%
  r8mat_print ( n, n+nrhs, a, '  The linear system:' );
%
%  Solve the systems.
%
  [ a, info ] = r8mat_solve ( n, nrhs, a );

  if ( info ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, '  The input matrix was singular.\n' );
    fprintf ( 1, '  The solutions could not be computed.\n' );
    return
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The computed solutions:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n
    for j = 1 : nrhs
      fprintf ( 1, '  %12f', a(i,n+j) );
    end
    fprintf ( 1, '\n' );
  end

  return
end


function [ r c ] = corner_ST( img,ptNum )
%[ r c ] = corner_ST( img )
%	Find corner points in image using Shi-Tomasi method
%   IMG should be gray.R and C are the coordinates of corners(col vec)

img = im2double(img);
h1 = fspecial('gauss',[6 6],1.5);
hd = imfilter(h1,[-1 1],'rep');
hd = hd(1:5,1:5); % use the HOG gradient
% hd = [-1 0 1];
imgdx = imfilter(img,hd,'rep');
imgdy = imfilter(img,hd','rep');

ker = fspecial('gauss',[5 5],1.5); % weight of the patch
imgdx2 = imfilter(imgdx.^2,ker,'rep');
imgdxdy = imfilter(imgdx.*imgdy,ker,'rep');
imgdy2 = imfilter(imgdy.^2,ker,'rep');

A = zeros(2,2,numel(img));
A(1,1,:) = imgdx2(:);
A(1,2,:) = imgdxdy(:);
A(2,1,:) = imgdxdy(:);
A(2,2,:) = imgdy2(:);
ev = real(eig2(A));

evTh = .1;
minEv = min(ev,[],2);
minEv = reshape(minEv,size(img));
R = (minEv > evTh*max(max(minEv)));
% fis(R)

Rmax = ordfilt2(minEv,9,ones(3));
Rcorner = (minEv == Rmax) & R; % non-maximal suppression
% fis(Rcorner)
I = find(Rcorner);

if exist('ptNum','var') && nnz(Rcorner) > ptNum
	selEvs = minEv(I); % find the ptNum corners with the largest ev
	[~,I1] = sort(selEvs,'descend');
	I = I(I1(1:ptNum));
end
[r c] = ind2sub(size(img),I); % points' positions

end

function ev = eig2(a) % eigenvalue of a 2*2 matrix
b = -(a(1,1,:)+a(2,2,:));
detA = a(1,1,:).*a(2,2,:)-a(1,2,:).*a(2,1,:);
delta = b.^2-4*detA;
ev = [-b+sqrt(delta),-b-sqrt(delta)]/2;
ev = reshape(ev,2,[])'; % N-by-2
end