% ------------------------------------------------------
% SwarmOps - Heuristic optimization for Matlab
% Copyright (C) 2003-2010 Magnus Erik Hvass Pedersen.
% Please see the file license.txt for license details.
% SwarmOps on the internet: http://www.Hvass-Labs.org/
% ------------------------------------------------------

% Many Optimizing Liaisons (MOL) optimization method is a
% simplification of PSO originally by Eberhart et al. (1, 2).
% MOL does not have any attraction to the particle's own best
% known position. It is similar to the "Social Only" PSO
% suggested by Kennedy (3) and was studied more thoroguhly
% by Pedersen et al. (4) who found it to sometimes outperform
% PSO and have behavioural parameters that were easier to tune.
% This is a parallelized version.
% Literature references:
% (1) J. Kennedy and R. Eberhart. Particle swarm optimization.
%     In Proceedings of IEEE International Conference on Neural
%     Networks, volume IV, pages 1942-1948, Perth, Australia, 1995
% (2) Y. Shi and R.C. Eberhart. A modified particle swarm optimizer.
%     In Proceedings of the IEEE International Conference on
%     Evolutionary Computation, pages 69-73, Anchorage, AK, USA, 1998.
% (3) J. Kennedy. The particle swarm: social adaptation of knowledge,
%     In: Proceedings of the IEEE International Conference on
%     Evolutionary Computation, Indianapolis, USA, 1997.
% (4) M.E.H. Pedersen and A.J. Chipperfield. Simplifying particle swarm
%     optimization. Applied Soft Computing, volume 10, pages 618-628, 2010.
% Parameters:
%     problem; name or handle of optimization problem, e.g. @myproblem.
%     data; data-struct, see e.g. the file myproblemdata.m
%     parameters; behavioural parameters for optimizer,
%                 see file molparameters.m
% Returns:
%     bestX; best found position in the search-space.
%     bestFitness; fitness of bestX.
%     evaluations; number of fitness evaluations performed.
function [bestX, bestFitness, evaluations] = molparallel(problem, data, parameters)

    % Copy data contents to local variables for convenience.
    n = data.Dim;
    acceptableFitness = data.AcceptableFitness;
    maxEvaluations = data.MaxEvaluations;
    lowerBound = data.LowerBound;
    upperBound = data.UpperBound;

    % Behavioural parameters for this optimizer.
    s = parameters(1);        % Swarm-size
    omega = parameters(2);    % Inertia weight.
    phiG = parameters(3);     % Swarm's best weight.

    % Initialize the velocity boundaries.
    range = upperBound-lowerBound;
    lowerVelocity = -range;
    upperVelocity = range;

    % Initialize swarm.
    x = initpopulation(s, n, data.LowerInit, data.UpperInit);    % Particle positions.
    v = initpopulation(s, n, lowerVelocity, upperVelocity);      % Velocities.

    % Compute fitness of initial particle positions. (Parallel)
    fitness = zeros(1, s); % Preallocate array for efficiency.
    parfor i=1:s
        fitness(i) = feval(problem, x(i,:), data);
    end

    % Determine best particle.
    [bestFitness, bestIndex] = min(fitness);
    bestX = x(bestIndex,:);

    % Perform optimization iterations until acceptable fitness
    % is achieved or the maximum number of fitness evaluations
    % has been performed.
    evaluations = s; % Fitness evaluations above count as iterations.
    while (evaluations < maxEvaluations) && (bestFitness > acceptableFitness)

        % Update particle velocities and positions. (Non-parallel)
	for i=1:s
            % Pick random weight.
            rG = rand(1, 1);

            % Update velocity for i'th particle.
            v(i,:) = omega * v(i,:) + rG * phiG * (bestX - x(i,:));

            % Bound velocity.
            v(i,:) = bound(v(i,:), lowerVelocity, upperVelocity);

            % Update position for i'th particle.
            x(i,:) = x(i,:) + v(i,:);

            % Bound position to search-space.
            x(i,:) = bound(x(i,:), lowerBound, upperBound);
        end

        % Compute fitness. (Parallel)
        % Only this fitness evaluation is parallelized
        % which makes synchronization easier.
        parfor i=1:s
            fitness(i) = feval(problem, x(i,:), data);
        end

        % Update swarm's best-known position. (Non-parallel)
        [newBestFitness, newBestIndex] = min(fitness);
        if newBestFitness < bestFitness
            % Update swarm's best-known fitness.
            bestFitness = newBestFitness;

            % Update swarm's best-known position.
            % This must be copied because the particles
            % will continue to move in the search-space.
            bestX = x(newBestIndex,:);
        end

        % Increment counter.
        evaluations = evaluations + s;
    end
end

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


function plotNonlinCon(prob,data,linear)
%PLOTNONLINCON Plot Nonlinear Constraints on the current figure
%   plotNonlinCon(prob)

%   Copyright (C) 2013 Jonathan Currie (I2C2)

if(nargin < 3), linear = false; end

xl = xlim; yl = ylim;
hold on;

%Colour
dkg = [0.2 0.2 0.2];
data.linear = linear;

%Ensure we have row format
if(isempty(prob.cl))
    prob = nmix2row(prob);
end

%Determine number of nonlinear constraints
no = length(prob.cl);
%Generate Constraint Surface Points
[x1,x2] = meshgrid(linspace(xl(1),xl(2),data.npts),linspace(yl(1),yl(2),data.npts));
nox = size(x1); noy = size(x2);
%Form Constraint Function
if(prob.sizes.ndec==1)
    con = @(x) prob.nlcon(x(1));
else
    con = prob.nlcon;
end

%Create surface of all constraints
obj = zeros(nox(1),noy(2),no);
for n = 1:nox(1)
    for m = 1:noy(2)
        x = data.fixval;
        if(data.ndec > 1)
            x(data.idx) = [x1(n,m) x2(n,m)]';
        else
            x(data.idx) = x1(n,m);
        end
        obj(n,m,:) = con(x);
    end
end

%Plot All General Nonlinear Constraints
plotNLCon(con,obj,prob.cl,prob.cu,x1,x2,dkg,data);

hold off;

% OLD CODE
% if(isempty(prob.nle))
%     prob = nrow2mix(prob,0);
% end
%
% %Generate Nonlinear Constraint Contours & Plot
% nocon = length(prob.nle);
% if(nocon)
%     [x1,x2] = meshgrid(linspace(xl(1),xl(2),npts),linspace(yl(1),yl(2),npts));
%     nox = size(x1);
%     noy = size(x2);
%     obj = zeros(nox(1),noy(2),nocon);
%     % create surface of all constraints
%     for n = 1:nox(1)
%         for m = 1:noy(2)
%             x = [x1(n,m) x2(n,m)]';
%             obj(n,m,:) = prob.nlcon(x);
%         end
%     end
%     %Plot them
%     for i = 1:nocon
%         %Inequality
%         if(prob.nle(i))
%             c = contour(x1,x2,obj(:,:,i),'color',dkg,'levellist',prob.nlrhs(i));
%             %Plot Hatch
%             if(~isempty(c))
%                 %See if we have multiple contours
%                 len = size(c,2)-1;
%                 if(c(2,1) ~= len)
%                     %Build contour array
%                     cstrt = 2; cend = []; n = 2; ind = 1;
%                     while(ind <= len)
%                         ind = ind + c(2,ind) + 1;
%                         cend(n-1) = ind-1; %#ok<AGROW>
%                         cstrt(n) = ind+1;  %#ok<AGROW>
%                         n = n + 1;
%                     end
%                 else
%                     cstrt = 2;
%                     cend = len;
%                 end
%                 %Plot each contour hatch
%                 for n = 1:length(cend)
%                     %Get contour vectors
%                     vecx = diff(c(1,cstrt(n):cend(n)));
%                     vecy = diff(c(2,cstrt(n):cend(n)));
%                     if(isempty(vecx) || isempty(vecy))
%                         continue;
%                     end
%                     %Rotate hatch lines based on infeasible region
%                     xt = [c(1,cstrt(n))+vecy(1) c(2,cstrt(n))-vecx(1)]'; %check rotated -90
%                     fval = prob.nlcon(xt);
%                     if((fval(i) <= prob.nlrhs(i) && prob.nle(i) == -1) || (fval(i) >= prob.nlrhs(i) && prob.nle(i) == 1)) %rotate 90
%                         hvecx = -vecy;
%                         hvecy = vecx;
%                     else %rotate -90
%                         hvecx = vecy;
%                         hvecy = -vecx;
%                     end
%                     %Normalize
%                     av = mean(sqrt(hvecx.^2 + hvecy.^2));
%                     dirs = atan2(hvecy,hvecx);
%                     hvecx = av*cos(dirs);
%                     hvecy = av*sin(dirs);
%                     %Shift origin
%                     hvecx = c(1,cstrt(n):cend(n)-1) + hvecx;
%                     hvecy = c(2,cstrt(n):cend(n)-1) + hvecy;
%                     %Plot
%                     line([c(1,cstrt(n):cend(n)-1)' hvecx']',[c(2,cstrt(n):cend(n)-1)' hvecy']','Color','k')
%                 end
%             else
%                 optiwarn('opti:plot','Cannot plot inequality constraint as contour data is empty!');
%             end
%         else
%             contour(x1,x2,obj(:,:,i),'color',[0 0 1],'levellist',prob.nlrhs(i));
%         end
%     end
% end
%
% hold off;


if 0
  % functionality test
  repmat([1 2; 3 4],2,4,2,2)
  repmat([1 2; 3 4],[2 4 2 2])
  repmat([1 2; 3 4],2)
  repmat(j,3,2)
  repmat('hello',3,2)
  repmat({7},3,2)
  repmat(sparse(7),3,2)
end

x = rand(300,1);
x = rand(10,1);
% run it once to load the definition
repmat(1,1,1);
niter = 100000/prod(size(x));
n = 100;
fprintf('repmat(x,1,n)\n');
tic; for i = 1:niter xrepmat(x,1,n); end; t0=toc;
fprintf('old repmat: %g\n',t0);
tic; for i = 1:niter repmat(x,1,n); end; t=toc;
fprintf('new repmat: %g (%g times faster)\n',t,t0/t);

if 0
  % repmat is faster than ones
  tic; for i = 1:niter ones(300,1000); end; toc
  tic; for i = 1:niter xrepmat(ones(300,1),1,1000); end; toc
  tic; for i = 1:niter repmat(1,300,1000); end; toc
end

if 0
  % zeros is faster than repmat (as expected)
  tic; for i = 1:niter zeros(300,1000); end; toc
  tic; for i = 1:niter repmat(zeros(300,1),1,1000); end; toc
  tic; for i = 1:niter xrepmat(0,300,1000); end; toc
end

if 0
  fprintf('new repmat:');
  tic; for i = 1:niter repmat(x',1000,1); end; toc
  fprintf('old repmat:');
  tic; for i = 1:niter xrepmat(x',1000,1); end; toc
end

if 0
  fprintf('new repmat:');
  tic; for i = 1:niter repmat(x,1000,1); end; toc
  fprintf('old repmat:');
  tic; for i = 1:niter xrepmat(x,1000,1); end; toc
end


% The COBRAToolbox: testSWIFTCORE.m
%
% Purpose:
%     - tests the basic functionality of swiftcore algorithm
%
% Authors:
%     - Original file: Mojtaba Tefagh, March 2019
%

global CBTDIR

% require the specified toolboxes and solvers
solvers = prepareTest('needsLP', true, 'requireOneSolverOf', {'gurobi','ibm_cplex'},'excludeSolvers', {'matlab', 'lp_solve','pdco'},'requiredToolboxes', {'statistics_toolbox'});

% save the current path
currentDir = pwd;

% initialize the test
testPass = fileparts(which('testSWIFTCORE.m'));
cd(testPass);

% set the cobra solver
solverLPOK = changeCobraSolver(solvers.LP{1}, 'LP', 0);

% load the model
model = getDistributedModel('ecoli_core_model.mat');
model.rev = double(model.lb < 0);
A = swiftcc(model.S, model.rev,solvers.LP{1});
model.S = model.S(:, A);
model.rev = model.rev(A);
model.ub = model.ub(A);
model.lb = model.lb(A);
model.rxns = model.rxns(A);
n = length(model.rev);
core = randsample(n, round(n/2));

fprintf(' -- Running swiftcore w/o reduction and using the %s solver...\n', solvers.LP{1});
[~, coreInd, ~] = swiftcore(model, core, ones(n, 1), 1e-10, false, solvers.LP{1});
assert(all(coreInd(core)));
A = swiftcc(model.S(:, coreInd), model.rev(coreInd), solvers.LP{1});
%A = swiftcc(model.S(:, coreInd), model.rev(coreInd));
assert(all(A.' == 1:length(A)));
fprintf(' -- Running swiftcore w/ reduction and using the %s solver...\n', solvers.LP{1});
[~, coreInd, ~] = swiftcore(model, core, ones(n, 1), 1e-10, true, solvers.LP{1});
assert(all(coreInd(core)));
A = swiftcc(model.S(:, coreInd), model.rev(coreInd),solvers.LP{1});
tmp=nnz(A.' == 1:length(A))/length(A)
bool=all(A.' == 1:length(A));
assert(bool);

% output a success message
fprintf('\nDone.\n');

% load the model
model = getDistributedModel('ecoli_core_model.mat');
model.rev = double(model.lb < 0);
A = fastcc(model, 1e-4, 0);

fprintf('\n -- Running swiftcc using the %s solver...\n', solvers.LP{1});
consistent = swiftcc(model.S, model.rev, solvers.LP{1});
assert(all(A == consistent));

[solverName, solverOK] = getCobraSolver('LP');
fprintf('\n -- Running swiftcc using the default LP solver, which is %s,....\n', solverName);
consistent = swiftcc(model.S, model.rev,solvers.LP{1});
assert(all(A == consistent));

% output a success message
fprintf('\nDone.\n');

% change the directory
cd(currentDir)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% runmcs.m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% test driver for running MCS
% with advice on how to choose the tuning parameters
%
% applied to the Jones test functions with default boxes
%
% To solve your own problem, copy this file (to ownmcs.m, say)
% and adapt the first part labelled `problem definition'.
% Then run the driver by typing `ownmcs' at the Matlab prompt.
%
% If you are not satisfied with the results, or if you want to play
% with the tuning parameters, you also need to adapt the second part
% labelled `change MCS settings'. In particular, for wide bounds,
% you'll probably get better results if you supply your own
% initialization list.
%
% On typing `runmcs' at the Matlab prompt,
% the unmodified file produces test results for the six-hump camel
% function; by only changing the data assignment you can also get
% results for the other test functions from Jones et al.
% You may also play with the bounds by modifying the default bounds.
%

clear; clear mex; clear global;
format compact;format long

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%% problem definition %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% define objective function
%
% Each function value f=f(x) is obtained by MCS using a call
% f=feval(fcn,data,x)
% where data is an arbitrary data object passed to mcs. If you have
% several data items, put them into a cell array or structure array
% called data.
% If there are no data, use fcn='feval' and the function name as data.
%
fcn = 'feval';
data = 'cam';	% select test function from Jones et al. test set
		% bra  n=2   Branin
		% cam  n=2   six-hump camel
		% gpr  n=2   Goldstein-Price
		% shu  n=2   Shubert
		% hm3  n=3   Hartman 3
		% s10  n=4   Shekel 10
		% sh5  n=4   Shekel 5
		% sh7  n=4   Shekel 7
		% hm6  n=6   Hartman 6
path(path,'jones');	% add path to directory with function

% define bounds on variables (+-inf allowed)
%
% u: column vector of lower bounds
% v: column vector of upper bounds
% u(k)<v(k) is required
%
[u,v,fglob] = defaults(data); 	% returns bounds used by Jones et al.
				% and known global optimum
dimension=length(u)		% show dimension
known_global_opt_value=fglob	% show known global minimum value
% u=[-5,0]';v=[10,15]';    		% bra default bounds
% u=[-3,-2]';v=[3,2]';     		% cam default bounds
% u=[-2,-2]';v=[2,2]';     		% gpr default bounds
% u=[-10,-10]';v=[10,10]'; 		% shu default bounds
% u=[0,0,0]';v=[1,1,1]';   		% hm3 default bounds
% u=[0,0,0,0]';v=[10,10,10,10]';   	% sh5,sh7,s10 default bounds
% u=[0,0,0,0,0,0]';v=[1,1,1,1,1,1]';   	% hm6 default bounds
% modify the problem to be unconstrained by activating the next line
% u = -Inf*ones(size(u));v=-u;

use_defaults=1
% *** If you just want to use the default settings,
% *** you don't need to edit the rest of the file,
% *** If you are not satisfied with the results
% *** (this may happen especially when your box bounds are very wide),
% *** or if you want to play with the tuning parameters,
% *** set use_defaults=0, and modify the rest of the file
% *** according to your curiosity or ingenuity

if use_defaults,
  % easy to use version - all parameters preset
  % defaults are being used, it suffices to call
  %%%%%%%%%%%%%%%%%% simple MCS call %%%%%%%%%%%%%%%%%%
  [xbest,fbest,xmin,fmi,ncall,ncloc]=mcs(fcn,data,u,v);
  % or, with less output,
  % [xbest,fbest]=mcs(fcn,data,u,v);

  xbest	  		% best point found
  fbest     		% best function value
  fglob			% global minimum (known for test functions)
  ncall	  		% number of function values used
  ncloc	  		% number of function values in local searches

  % xmin	  	% columns are points in 'shopping basket'
			% may be good alternative local minima
  % fmi	  		% function values in 'shopping basket'
  nbasket = length(fmi) % number of points in 'shopping basket'

  return;
end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%% change MCS settings %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% flexible use version - all parameters may be modified

%
% define amount of output printed
prt = 1;	% print level
		% prt = 0: no output
		% prt = 1: # sweep, minimal nonempty level, # f-calls,
		%          best point and function value
		% prt > 1: in addition levels and function values of
		%          boxes containing the known global minimizers
		%          of a test function

% define global strategy
%
% smax governs the relative amount of global versus local search. By
% increasing smax, more weight is given to global search.
%
% Increasing or decreasing stop(1) increases or decreases the amount
% of work allowed before concluding that nothing more is gained;
% the default choice is quite conservative, and may try to locate
% a better point long after the global minimum has been found.
% stop(1)=5 works for many easier problems, too, with much fewer
% wasted function values.
%
% Increasing nf allows to spend more time on boxes that have a chance
% on their level to contain better points. This may be important for
% hard problems, or for problems with very wide bounds.
%
% But in each case, it is unclear in advance what change would be most
% beneficial to a particular problem.
% We had very mixed experience; if you have many similar problems to
% solve, the best thing to do is to experiment with a few problems to
% find the best values, and to use these on the others.
%
n = length(u);		% problem dimension
smax = 5*n+10;		% number of levels used
nf = 50*n^2; 		% limit on number of f-calls
stop(1) = 3*n;		% = m, integer defining stopping test
stop(2) = -inf;		% = freach, function value to reach
			% if m>0, run until m sweeps without progress
			% if m=0, run until fbest<=freach
			% (or about nf function calls were used)

if 0, 	% known global optimum, for tests only
	% then the entries of stop have a different meaning
  stop(1) = 1.e-4;	% run until this relative error is achieved
  stop(2) = fglob;	% known global optimum value
  stop(3) = 1.e-10;	% stopping tolerance for tiny fglob
end;

% define initialization strategy
%
% for wide boxes, it is advisable (and for unbounded search regions
% strongly advisable) to define a customized initialization list
% that contains for each coordinate at least three reasonable values.
% Without such an initialization list, mcs makes default assumptions
% that roughly amount to estimating reasonable magnitudes from the
% bounds and in case iinit=1 from assuming order unity if this is
% within the bounds.
%
% for a self-defined initialization list, the user should
% write an m-script file init0.m containing a matrix x0 with n
% rows and at least 3 columns and two n-vectors l and L
% the ith column of x0 contains the initialization list
% values for the ith coordinate, their number is L(i), and
% x0(i,l(i)) is the ith coordinate of the initial point

iinit = 0;	% 0: simple initialization list
		%    (default for finite bounds;
		%     do not use this for very wide bounds)
		% 1: safeguarded initialization list
		%    (default for unbounded search regions)
		% 2: (5*u+v)/6, (u+v)/2, (u+5*v)/6
		% 3: initialization list with line searches
		% else: self-defined initialization list
		%       stored in file init0.m

% parameters for local search
%
% A tiny gamma (default) gives a quite accurate but in higher
% dimensions slow local search. Increasing gamma leads to less work
% per local search but a less accurately localized minimizer
%
% If it is known that the Hessian is sparse, providing the sparsity
% pattern saves many function evaluations since the corresponding
% entries in the Hessian need not be estimated. The default pattern
% is a full matrix.
%
local = 50;		% local = 0: no local search
			% else: maximal number of steps in local search
gamma = eps;		% acceptable relative accuracy for local search
hess = ones(n,n);	% sparsity pattern of Hessian

% defaults are not being used, use the full calling sequence
% (including at least the modified arguments)
%%%%%%%%%%%%%%%%%%%%%%% full MCS call %%%%%%%%%%%%%%%%%%%%%%
[xbest,fbest,xmin,fmi,ncall,ncloc]=...
  mcs(fcn,data,u,v,prt,smax,nf,stop,iinit,local,gamma,hess);

xbest	  		% best point found
fbest     		% best function value
fglob			% global minimum (known for test functions)
ncall	  		% number of function values used
ncloc	  		% number of function values in local searches

% xmin	  		% columns are points in 'shopping basket'
			% may be good alternative local minima
% fmi	  		% function values in 'shopping basket'
nbasket = length(fmi) 	% number of points in 'shopping basket'


function SimRndResults = SimRnd(Model, RndParam, Opt)
%VaryRndParam Multi Voxel simulation of normally distributed parameters

fields = fieldnames(RndParam);
n = length(RndParam.(fields{1})); % number of voxels

% Create waitbar
h = waitbar(0, sprintf('Data 0/%0.0f',n), 'Name', 'Simulating data',...
    'CreateCancelBtn', 'if ~strcmp(get(gcbf,''Name''),''canceling...''), setappdata(gcbf,''canceling'',1); set(gcbf,''Name'',''canceling...''); else delete(gcbf); end');
setappdata(h,'canceling',0)
setappdata(0,'Cancel',0);

tic;
for ii = 1:n
    for ix=1:length(Model.xnames)
        x(ix) = RndParam.(Model.xnames{ix})(ii);
    end
    Fit = Model.Sim_Single_Voxel_Curve(x,Opt,0);

    if ii==1 % initialize structure at first Sim
        fields = fieldnames(Fit);
        for vox = 1:length(fields)
            SimRndResults.(fields{vox}) = nan(n,1);
        end
    end

    for jj = 1:length(fields)
        SimRndResults.(fields{jj})(ii) = Fit.(fields{jj})(1);
    end

    % Update waitbar
    if getappdata(h,'canceling');  break;  end
    waitbar(ii/n,h,sprintf('Data %0.0f/%0.0f',ii,n));
end

delete(h);
SimRndResults.time = toc
SimRndResults.fields = fields;
SimRndResults = AnalyzeResults(RndParam, SimRndResults);
end

function Results = AnalyzeResults(Input, Results)
Fields = intersect(fieldnames(Input), fieldnames(Results));
for ii = 1:length(Fields)
    n = length(Input.(Fields{ii}));
    Results.Error.(Fields{ii})    = Results.(Fields{ii}) - Input.(Fields{ii}) ;
    Results.PctError.(Fields{ii}) = 100*(Results.(Fields{ii}) - Input.(Fields{ii})) ./ Input.(Fields{ii});
    Results.MPE.(Fields{ii})      = 100/n*sum((Results.(Fields{ii}) - Input.(Fields{ii})) ./ Input.(Fields{ii}));
    Results.RMSE.(Fields{ii})     = sqrt(sum((Results.(Fields{ii}) - Input.(Fields{ii})).^2 )/n);
    Results.NRMSE.(Fields{ii})    = Results.RMSE.(Fields{ii}) / (max(Input.(Fields{ii})) - min(Input.(Fields{ii})));
end
end


function showscene(cameras,voxels)
%SHOWSCENE: show a carve scene, including cameras, images and the model
%
%   SHOWSCENE(CAMERAS,VOXELS) shows the specified list of CAMERAS and the
%   current model as a surface fitted around VOXELS.
%
%   Example:
%   >> camera = loadcameradata(1);
%   >> camera.Silhouette = getsilhouette( camera.Image );
%   >> voxels = carve( makevoxels(50), camera );
%   >> showscene( camera, voxels );

%   Copyright 2005-2009 The MathWorks, Inc.
%   $Revision: 1.0 $    $Date: 2006/06/30 00:00:00 $

error( nargchk( 1, 2, nargin ) );

%% Plot each camera centre
set(gca,'DataAspectRatio',[1 1 1])
hold on

N = numel(cameras);
for ii=1:N
    spacecarving.showcamera(cameras(ii));
end
xlabel('X')
ylabel('Y')
zlabel('Z')

%% And show a surface around the object
if nargin>1 && ~isempty( voxels )
    spacecarving.showsurface( voxels );
end

%% Light the scene and adjust the view angle to make it a bit easier on
% the eye
view(3);
grid on;
light('Position',[0 0 1]);
axis tight


function [] = twod_to_tecplot(x,e_conn,u,filename,title)
%------------------------------------------------------------------------------
%  twod_to_tecplot - function that accepts 2D finite element data and writes
%                    and input file to the graphics program Tecplot.
%
%  Usage:
%         [] = twod_to_tecplot(x,e_conn,u,filename,title)
%
%  Variables:     x
%                      spatial coordinates  (nodes x 2)
%                 e_conn
%                      element connectivity matrix  (3 nodes are used)
%                 u
%                      field variables
%                 filename
%                      name for the output tecplot file
%                 title
%                      title string required by tecplot
%------------------------------------------------------------------------------

[n_node,n_var] = size(u);
[n_elem,n_dof] = size(e_conn);

[fid] = fopen(filename,'w');

fprintf(fid,strcat(strcat('Title="',title),'"\n'));

temp_str = 'Variables="x","y"';
for i=1:n_var
  temp_str = strcat(strcat(temp_str,strcat(',"vec',strcat(num2str(i),'"'))));
end
temp_str = strcat(temp_str,'\n');
fprintf(fid,temp_str);

temp_str = 'Zone N = ';
temp_str = strcat( temp_str, num2str(n_node) );
temp_str = strcat( temp_str, ', E = ' );
temp_str = strcat( temp_str, num2str(n_elem) );
temp_str = strcat( temp_str, ', DATAPACKING = POINT, ZONETYPE = FETRIANGLE\n' );
fprintf(fid,temp_str);

print_str = ' %10.5g  %10.5g ';
for i=1:n_var
  print_str = strcat( print_str, ' %10.5g ' );
end
print_str = strcat( print_str, '\n' );

for i=1:n_node
  fprintf(fid,print_str,x(i,:),u(i,:));
end

print_str = ' %6d  %6d  %6d \n';
for i=1:n_elem
  fprintf(fid,print_str,e_conn(i,1:3));
end

fclose(fid);
% end function output_to_tecplot


function msm_to_mm_array_real_skewsymmetric ( output_filename, a )

%*****************************************************************************80
%
%% MSM_TO_MM_ARRAY_REAL_SKEWSYMMETRIC writes a "matrix array real skew-symmetric" Matrix Market file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 November 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the name of the file to which the information
%    should be written.
%
%    Input, sparse matrix A, the NROW by NCOL matrix, stored in MATLAB sparse
%    matrix format, which is to be written to the file.
%
  [ nrow, ncol ] = size ( a );

  fid = fopen ( output_filename, 'wt+' );

  if ( fid < 0 );
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MSM_TO_MM_ARRAY_REAL_SKEWSYMMETRIC - Fatal error!\n' );
    fprintf ( 1, '  Cannot open the output file.\n' );
    error ( 'MSM_TO_MM_ARRAY_REAL_SKEWSYMMETRIC - Fatal error!' );
  end

  fprintf ( fid, '%%%%MatrixMarket matrix array real skew-symmetric\n');
  fprintf ( fid, '%%%%  Created by MSM_TO_MM_ARRAY_REAL_SKEWSYMMETRIC.M\n' );
  fprintf ( fid, '  %d  %d\n', nrow, ncol );

  for j = 1 : ncol
    for i = j + 1 : nrow
      fprintf ( fid, '  %f\n', a(i,j) );
    end
  end

  fclose ( fid );

  return
end


function a = tril(a,k)
%TRIL         Implements  tril(a,k)  for hessians
%
%   c = tril(a,k)
%
% functionality as Matlab function tril for matrices
%

% written  04/04/04     S.M. Rump
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  if nargin==1
    k = 0;
  end

  a.x = tril(a.x,k);
  index = ( tril( ones(size(a.x)) , k ) == 0 );
  a.dx(:,index) = 0;
  a.hx(:,index) = 0;


function [newF, logQaa] = sampleFfromRestrictedSet( aa, anchorObjIDs, LL, propFeatIDs, propPiIN, myFPr, TargetPsi )
% Sample feature assignments to the feature pair indicated by propFeatIDs

switch aa
    case anchorObjIDs(1)
        restrictedFeatureSet = [1 0; 1 1];
    case anchorObjIDs(2)
        restrictedFeatureSet = [0 1; 1 1];
    otherwise
        restrictedFeatureSet = [0 1; 1 0; 1 1];
end

availFeatIDs = propPiIN.availFeatIDs;
kiloc = find( availFeatIDs == propFeatIDs(1) );
kjloc = find( availFeatIDs == propFeatIDs(2) );

logPr = -Inf(1,3);
for featureVals = restrictedFeatureSet'
    featureVals = featureVals'; % make it row vector again
    featureCombo = (featureVals * [10;1] );

    switch featureCombo
        case 01
            % propPi = TS.obj(ii) with featIDs(1) deleted
            %propPi = buildTransStructForProposal( propTS, hyperparams, model, aa, propFeatIDs(1), 0);
            %propPi = propPi.obj(aa);
            %propPi = propPiIN;
            keepIDs = [1:kiloc-1 kiloc+1:length(availFeatIDs)];
        case 10
            keepIDs = [1:kjloc-1 kjloc+1:length(availFeatIDs)];
            % propPi = TS.obj(ii) with featIDs(2) deleted
            %propPi = buildTransStructForProposal( propTS, hyperparams, model, aa, propFeatIDs(2), 0);
            %propPi = propPi.obj(aa);
        case 11
            keepIDs = 1:length(availFeatIDs);
            %propPi = propPiIN; % propTS.obj(aa);
    end
    propPi.availFeatIDs = propPiIN.availFeatIDs( keepIDs );
    propPi.pi_z = propPiIN.pi_z( keepIDs, keepIDs );
    propPi.pi_init = propPiIN.pi_init( keepIDs );

    logPrY = calcLogMargPrObsSeqFAST(  LL( propPi.availFeatIDs, :), propPi.pi_z );
    switch aa
        case anchorObjIDs(1)
            logPrF = featureVals(2) * log( myFPr(2) ) + (1-featureVals(2)).*log( 1-myFPr(2) );
        case anchorObjIDs(2)
            logPrF = featureVals(1) * log( myFPr(1) ) + (1-featureVals(1)).*log( 1-myFPr(1) );
        otherwise
            logPrF = sum( featureVals .* log( myFPr ) + (1-featureVals).*log( 1-myFPr ) );
    end

    switch featureCombo
        case 01
            logPr(1) = logPrY + logPrF;
        case 10
            logPr(2) = logPrY + logPrF;
        case 11
            logPr(3) = logPrY + logPrF;
    end
end
ps = exp( logPr - max(logPr)  );
if isempty( TargetPsi ) || ~exist('TargetPsi', 'var')
    [choice] = multinomial_single_draw( ps );
else
    targetVals = TargetPsi.F( aa,  TargetPsi.activeFeatIDs );
    switch ( targetVals * [10;1] )
        case 01
            choice = 1;
        case 10
            choice = 2;
        case 11
            choice = 3;
    end
end
switch choice
    case 1
        newF = [0 1];
    case 2
        newF = [1 0];
    case 3
        newF = [1 1];
end

logQaa = log( ps(choice)/sum(ps)  );

%assert( ~isinf( logQaa ), 'Bad Calculation of Proposal Prob.' );
%if isinf( logQaa )
%    fprintf( 'WARNING: Forced transition highly improbable (-Inf)\n' );
%end


function hf_out = lhs_operation_joint(hf, samplesf, reg_filter, init_samplef, XH, init_hf, proj_reg)

% This is the left-hand-side operation in Conjugate Gradient

hf_out = cell(size(hf));

% Extract projection matrix and filter separately
P = cellfun(@real, hf(2,1,:), 'uniformoutput',false);
hf = hf(1,1,:);

% Get sizes
num_features = length(hf);
filter_sz = zeros(num_features,2);
for k = 1:num_features
    filter_sz(k,:) = [size(hf{k},1), size(hf{k},2)];
end
[~, k1] = max(filter_sz(:,1));  % Index for the feature block with the largest spatial size
block_inds = 1:num_features;
block_inds(k1) = [];
output_sz = [size(hf{k1},1), 2*size(hf{k1},2)-1];

% Compute the operation corresponding to the data term in the optimization
% (blockwise matrix multiplications)
%implements: A' diag(sample_weights) A f

% sum over all features and feature blocks
sh = sum(bsxfun(@times, samplesf{k1}, hf{k1}), 3);    % assumes the feature with the highest resolution is first
pad_sz = cell(1,1,num_features);
for k = block_inds
    pad_sz{k} = (output_sz - [size(hf{k},1), 2*size(hf{k},2)-1]) / 2;

    sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,:) = ...
        sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,:) + sum(bsxfun(@times, samplesf{k}, hf{k}), 3);
end

% weight all the samples and take conjugate
% sh = bsxfun(@times,sample_weights,sh);
sh = conj(sh);

% multiply with the transpose
hf_out1 = cell(1,1,num_features);
hf_out1{k1} = conj(sum(bsxfun(@times, sh, samplesf{k1}), 4));
for k = block_inds
    hf_out1{k} = conj(sum(bsxfun(@times, sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end,1,1,:), samplesf{k}), 4));
end

% compute the operation corresponding to the regularization term (convolve
% each feature dimension with the DFT of w, and the tramsposed operation)
% add the regularization part
% hf_conv = cell(1,1,num_features);
for k = 1:num_features
    reg_pad = min(size(reg_filter{k},2)-1, size(hf{k},2)-1);

    % add part needed for convolution
    hf_conv = cat(2, hf{k}, conj(rot90(hf{k}(:, end-reg_pad:end-1, :), 2)));

    % do first convolution
    hf_conv = convn(hf_conv, reg_filter{k});

    % do final convolution and put toghether result
    hf_out1{k} = hf_out1{k} + convn(hf_conv(:,1:end-reg_pad,:), reg_filter{k}, 'valid');
end

% Stuff related to the projection matrix

% B * P
BP_cell = cell(1,1,num_features);
for k = 1:num_features
    BP_cell{k} = sum(bsxfun(@times, reshape(reshape(init_samplef{k}, [], size(init_samplef{k},3)) * P{k}, size(init_samplef{k},1), size(init_samplef{k},2), []), init_hf{k}), 3);
end

BP = BP_cell{k1};
for k = block_inds
    BP(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) = ...
        BP(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) + BP_cell{k};
end

% multiply with the transpose: A^H * BP
hf_out{1,1,k1} = hf_out1{k1} +  bsxfun(@times, BP, conj(samplesf{k1}));

% B^H * BP
fBP = cell(1,1,num_features);
fBP{k1} = reshape(bsxfun(@times, conj(init_hf{k1}), BP), [], size(init_hf{k1},3));

% Compute proj matrix part: B^H * A_m * f
shBP = cell(1,1,num_features);
shBP{k1} = reshape(bsxfun(@times, conj(init_hf{k1}), sh), [], size(init_hf{k1},3));

for k = block_inds
    % multiply with the transpose: A^H * BP
    hf_out{1,1,k} = hf_out1{k} +  bsxfun(@times, BP(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end), conj(samplesf{k}));

    % B^H * BP
    fBP{k} = reshape(bsxfun(@times, conj(init_hf{k}), BP(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end)), [], size(init_hf{k},3));

    % Compute proj matrix part: B^H * A_m * f
    shBP{k} = reshape(bsxfun(@times, conj(init_hf{k}), sh(1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end)), [], size(init_hf{k},3));
end

% hf_out2 = cell(1,1,num_features);
for k = 1:num_features
    fi = size(hf{k},1) * (size(hf{k},2)-1) + 1;  % index where the last frequency column starts

    % B^H * BP
    hf_out2 = 2*real(XH{k} * fBP{k} - XH{k}(:,fi:end) * fBP{k}(fi:end,:)) + proj_reg * P{k};

    % Compute proj matrix part: B^H * A_m * f
    hf_out{2,1,k} = hf_out2 + (2*real(XH{k} * shBP{k} - XH{k}(:,fi:end) * shBP{k}(fi:end,:)));
end
end


%%******************************************************************
%% infeaspt: generate an initial point for sdp.m
%%
%%  [X0,y0,Z0] = infeaspt(blk,At,C,b,options,scalefac);
%%
%%  options = 1  if want X0,Z0 to be scaled identity matrices
%%          = 2  if want X0,Z0 to be scalefac*(identity matrices).
%%*****************************************************************
%% SDPT3: version 4.0
%% Copyright (c) 1997 by
%% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu
%% Last Modified: 16 Sep 2004
%%*****************************************************************

   function [X0,y0,Z0] = infeaspt(blk,At,C,b,options,scalefac);
%%
   if (nargin < 5); options = 1; end;
   if (options == 1); scalefac = []; end;
   if (options == 2) & (nargin < 6); scalefac = 1000; end;
   if (scalefac <= 0); error('scalefac must a positive number'); end;
%%
   if ~iscell(At); At = {At}; end;
   if ~iscell(C);  C = {C}; end;
   m = length(b);
   if all(size(At) == [size(blk,1) m]);
      convertyes = zeros(size(blk,1),1);
      for p = 1:size(blk,1)
         if strcmp(blk{p,1},'s') & all(size(At{p,1}) == sum(blk{p,2}))
            convertyes(p) = 1;
         end
      end
      if any(convertyes)
         At = svec(blk,At,ones(size(blk,1),1));
      end
   end;
%%
   %%[blk,At,C,b] = validate(blk,At,C,b);
%%
   X0 = cell(size(C)); Z0 = cell(size(C));
   m = length(b);
   for p = 1:size(blk,1);
      pblk = blk(p,:);
      blktmp = pblk{2};
      n = length(C{p});
      y0 = zeros(m,1);
      b2 = 1 + abs(b');
      if (options == 1);
         if strcmp(pblk{1},'s');
            normAni = [];
            X0{p} = sparse(n,n); Z0{p} = sparse(n,n);
            ss = [0, cumsum(blktmp)];
            tt = [0, cumsum(blktmp.*(blktmp+1)/2)];
            for i = 1:length(pblk{2})
               if ~isempty(At{p,1})
                  pos = [tt(i)+1 : tt(i+1)];
                  Ai = At{p,1}(pos,:);
                  normAni = 1+sqrt(sum(Ai.*Ai));
               end
               if (length(At(p,:)) >= 2) %% for low rank constraints
                  dd = At{p,3};
                  qq = [0, cumsum(pblk{3})]; normtmp = ones(1,length(pblk{3}));
                  idxD = [0; find(diff(dd(:,1))); size(dd,1)];
                  for k = 1:length(pblk{3})
                      idx = [qq(k)+1 : qq(k+1)];
                      idx2 = [idxD(k)+1: idxD(k+1)];
                      Ak = At{p,2}(:,idx);
                      ii = dd(idx2,2)-qq(k); %% undo cumulative indexing
                      jj = dd(idx2,3)-qq(k);
                      len = pblk{3}(k);
                      Dk = spconvert([ii,jj,dd(idx2,4); len,len,0]);
                      tmp = Ak'*Ak*Dk;
                      normtmp(1,k) = 1+sqrt(sum(sum(tmp.*tmp')));
                  end
                  normAni = [normAni, normtmp];
               end
               pos = [ss(i)+1 : ss(i+1)];  ni = length(pos);
               tmp = C{p}(pos,pos);
               normCni = 1+sqrt(sum(sum(tmp.*tmp)));
               const  = 10; %%--- old: const = 1;
               constX = max([const,sqrt(ni),ni*(b2./normAni)]);
               constZ = max([const,sqrt(ni),normAni,normCni]);
               X0{p}(pos,pos) = constX*spdiags(1+1e-10*randmat(ni,1,0,'u'),0,ni,ni);
               Z0{p}(pos,pos) = constZ*spdiags(1+1e-10*randmat(ni,1,0,'u'),0,ni,ni);
            end
         elseif strcmp(pblk{1},'q');
            s = 1+[0, cumsum(blktmp)];
            len = length(blktmp);
            normC = 1+norm(C{p});
            normA = 1+sqrt(sum(At{p,1}.*At{p,1}));
            idenqX = zeros(sum(blktmp),1);
            idenqZ = zeros(sum(blktmp),1);
            idenqX(s(1:len)) = max([1,b2./normA])*sqrt(blktmp') ;
            idenqZ(s(1:len)) = max([sqrt(blktmp); max([normA,normC])*ones(1,len)])';
            idenqX(s(1:len)) = idenqX(s(1:len)).*(1+1e-10*randmat(len,1,0,'u'));
            idenqZ(s(1:len)) = idenqZ(s(1:len)).*(1+1e-10*randmat(len,1,0,'u'));
            X0{p} = idenqX;
            Z0{p} = idenqZ;
         elseif strcmp(pblk{1},'l');
            normC = 1+norm(C{p});
            normA = 1+sqrt(sum(At{p,1}.*At{p,1}));
            const = 10; %%--- old: const =1;
            constX = max([const,sqrt(n),sqrt(n)*b2./normA]);
            constZ = max([const,sqrt(n),normA,normC]);
            X0{p} = constX*(1+1e-10*randmat(n,1,0,'u'));
            Z0{p} = constZ*(1+1e-10*randmat(n,1,0,'u'));
         elseif strcmp(pblk{1},'u');
            X0{p} = sparse(n,1);
            Z0{p} = sparse(n,1);
         else
            error(' blk: some fields not specified correctly');
         end;
      elseif (options == 2);
         if strcmp(pblk{1},'s');
            n = sum(blktmp);
            X0{p} = scalefac*spdiags(1+1e-10*randmat(n,1,0,'u'),0,n,n);
            Z0{p} = scalefac*spdiags(1+1e-10*randmat(n,1,0,'u'),0,n,n);
         elseif strcmp(pblk{1},'q');
            s = 1+[0, cumsum(blktmp)];
            len = length(blktmp);
            idenq = zeros(sum(blktmp),1);
            idenq(s(1:len)) = 1+1e-10*randmat(len,1,0,'u');
            X0{p} = scalefac*idenq;
            Z0{p} = scalefac*idenq;
         elseif strcmp(pblk{1},'l');
            X0{p} = scalefac*(1+1e-10*randmat(n,1,0,'u'));
            Z0{p} = scalefac*(1+1e-10*randmat(n,1,0,'u'));
         elseif strcmp(pblk{1},'u');
            X0{p} = sparse(n,1);
            Z0{p} = sparse(n,1);
         else
            error(' blk: some fields not specified correctly');
         end
      end
   end
%%********************************************************************


function [wnew,freqnew]=updateGlyph(P,X,C,w,a,s,freq)
%Syntax: [wnew,freqnew]=updateGlyph(P,X,C,w,a,s,freq)
%____________________________________________________
%
% Weight matrix update of a Spherical Self-Organized Feature Map.
%
% wnew is the updated weights' matrix.
% freqnew is the updated count-dependent parameter.
% P is the A-by-B matrix with the patterns to be classified.
% X is the N-by-3 matrix with the cartesian coordinates of the points on
%   the sphere.
% C is a cell array with the neighbors. The {i,j} cell represents the
%   neighbors of radius i of the j-th sphere point.
% w is the weights matrix to be updated.
% a is the training parameter.
% s is the neighborhood size parameter.
% freq is the count-dependent parameter.
%
%
% References:
%
% Sangole A., Knopf G. K. (2002): Representing high-dimensional data sets
% as close surfaces. Journal of Information Visualization 1: 111-119
%
% Sangole A., Knopf G. K. (2003): Geometric representations for
% high-dimensional data using a spherical SOFM. International Journal of
% Smart Engineering System Design 5: 11-20
%
% Sangole A., Knopf G. K. (2003): Visualization of random ordered numeric
% data sets using self-organized feature maps. Computers and Graphics 27:
% 963-976
%
% Sangole A. P. (2003): Data-driven Modeling using Spherical
% Self-organizing Feature Maps. Doctor of Philosophy (Ph.D.) Thesis.
% Department of Mechanical and Materials Engineering. Faculty of
% Engineering. The University of Western Ontario, London, Ontario, Canada.
%
%
% Archana P. Sangole, PhD., P.E. (TX chapter)
% School of Physical & Occupational Therapy
% McGill University
% 3654 Promenade Sir-William-Osler
% Montreal, PQ, H3G 1Y5
% e-mail: archana.sangole@mail.mcgill.ca
%
% CRIR, Rehabilitation Institute of Montreal
% 6300 Ave Darlington
% Montreal, PQ, H3S 2J5
% Tel: 514.340.2111 x2188
% Fax: 514.340.2154
%
%
% Alexandros Leontitsis, PhD
% 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
%
% 23-Mar-2006

if nargin<2 | isempty(P)==1 | isempty(X)==1
    error('More input arguments needed. Both P and X are rquired.');
else
    % P must be an A-by-B matrix
    if ndims(P)~=2
        error('P must be an A-by-B matrix.');
    end
    % X must be an M-by-3 matrix
    if size(X,2)~=3 | ndims(X)~=2
        error('X must be an N-by-3 matrix.');
    end
end

if isempty(C)==0
    % C and X must be of the same length
    if length(C)~=length(X)
        error('C and X must be of the same length.');
    end
    % Set the neighborhood radious
    r=size(C,2);
    % Set the h function
    h=exp(-(1:r).^2/(s*r));
end

if nargin<4 | isempty(w)==1
    w=randn(size(X,1),size(P,2));
    for i=1:size(X,2)
        w(:,i)=w(:,i)*std(P(:,i));
    end
else
    % w must be an N-by-B matrix
    if size(w,1)~=size(X,1) | size(w,2)~=size(P,2) | ndims(X)~=2
        error('w must be an N-by-B matrix.');
    end
end

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

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

if nargin<7 | isempty(freq)==1
    freq=zeros(length(X),1);
else
    % freq must be a vector
    if min(size(freq))>1
        error('freq must be a vector.');
    end
    % freq must have the same length with X
    if length(freq)~=length(X)
        error('freq must have the same length with X.');
    end
end

% Initialize the weights
wnew=w;

% Initialize freqnew
freqnew=freq;

% Randomize the order of the patterns
q=randperm(size(P,1));

% For each uniformly random pattern
for j=1:size(P,1)
    % Measure the difference between the current P and all the weights
    A=q(j)*ones(size(wnew,1),1);
    d=P(A,:)-wnew;
    % Calculate the norm and apply the count-dependent parameter
    d=sqrt(sum((d.^2)'))'.*(freqnew+1);
    % Obtain the minimum distance and the corresponding index
    [D,I]=min(d);
    % Calculate the new weights
    wnew(I,:)=wnew(I,:)+a*(P(q(j),:)-wnew(I,:));
    % If the neighborhood matrix is given
    if isempty(C)==0
        % For each neghborhood radius
        for k=1:r
            A=q(j)*ones(size(C{I,k}));
            % Calculate the new weights of the neighbors
            wnew(C{I,k},:)=wnew(C{I,k},:)+a*h(k)*(P(A,:)-wnew(C{I,k},:));
            % Update the count-dependent parameter for the neighbors
            freqnew(C{I,k})=freqnew(C{I,k})+h(k);
        end
    end
    % Update the count-dependent parameter
    freqnew(I)=freqnew(I)+1;
end


% try first with Recon3D
load Recon3DModel_301.mat
start = 'xol7aone[r]';
stop = 'cholate[c]';
s=' ';
osenseStr = 'max';

% add sink reaction for start
model = addReaction(model,['start_', start],'reactionFormula',[start,s,'-->']);
model = addReaction(model,['stop_', stop],'reactionFormula',['-->',s,stop]);
printRxnFormula(model,model.rxns(end-1:end))

%% maximise flux through this dummy stop reaction
model = changeObjective(model,['stop_', stop]);
%force flux through this dummy start reaction
model = changeRxnBounds(model,['start_', start],-1000,'b');
model = changeRxnBounds(model,['stop_', stop],1000,'b');
model = changeRxnBounds(model,'sink_cholate[c]',0,'b');
%%
model0=model;

%%
[vSparse, sparseRxnBool1, essentialRxnBool]  = sparseFBA(model, osenseStr);
model.rxns(sparseRxnBool1)
nnz(sparseRxnBool1)
nnz(vSparse)

%%
rxnPenalty = ones(length(model.rxns),1);
param.printLevel = 1;
param.regularizeOuter = 0;
param.theta=0.1;
[solution,sparseRxnBool2] = findSparsePathway(model,rxnPenalty,param);
model.rxns(sparseRxnBool2)
nnz(sparseRxnBool2)
nnz(solution.v)

%check that both approaches give a sparse solution
assert(nnz(sparseRxnBool1)==nnz(sparseRxnBool2))


classdef PitchTermCondition < AbstractEventTerminationCondition
    %BankAngleTermCondition Summary of this class goes here
    %   Detailed explanation goes here

    properties
        steeringModel(1,1) AbstractSteeringModel = RollPitchYawPolySteeringModel.getDefaultSteeringModel();
        targetPitchAngle(1,1) double = 0;
        bodyInfo KSPTOT_BodyInfo
    end

    methods
        function obj = PitchTermCondition(targetPitchAngle)
            obj.targetPitchAngle = targetPitchAngle;
        end

        function evtTermCondFcnHndl = getEventTermCondFuncHandle(obj)
            evtTermCondFcnHndl = @(t,y) obj.eventTermCond(t,y, obj.targetPitchAngle, obj.steeringModel, obj.bodyInfo);
        end

        function initTermCondition(obj, initialStateLogEntry)
            obj.steeringModel = initialStateLogEntry.steeringModel;
            obj.bodyInfo = initialStateLogEntry.centralBody;
        end

        function name = getName(obj)
            name = sprintf('Pitch Angle (%.3f deg)', rad2deg(obj.targetPitchAngle));
        end

        function tf = shouldBeReinitOnRestart(obj)
            tf = false;
        end

        function params = getTermCondUiStruct(obj)
            params = struct();

            params.paramName = 'Target Pitch Angle';
            params.paramUnit = 'deg';
            params.useParam = 'on';
            params.useStages = 'off';
            params.useTanks = 'off';
            params.useEngines = 'off';
            params.useStopwatches = 'off';

            params.value = rad2deg(obj.targetPitchAngle);
            params.refStage = LaunchVehicleStage.empty(1,0);
            params.refTank = LaunchVehicleEngine.empty(1,0);
            params.refEngine = LaunchVehicleEngine.empty(1,0);
            params.refStopwatch = LaunchVehicleStopwatch.empty(1,0);
        end

        function optVar = getNewOptVar(obj)
            optVar = PitchAngleTermCondOptimVar(obj);
        end

        function optVar = getExistingOptVar(obj)
            optVar = obj.optVar;
        end

        function tf = usesStage(obj, stage)
            tf = false;
        end

        function tf = usesEngine(obj, engine)
            tf = false;
        end

        function tf = usesTank(obj, tank)
            tf = false;
        end

        function tf = usesEngineToTankConn(obj, engineToTank)
            tf = false;
        end

        function tf = usesStopwatch(obj, stopwatch)
            tf = false;
        end
    end

    methods(Static)
        function termCond = getTermCondForParams(paramValue, stage, tank, engine, stopwatch)
            termCond = PitchTermCondition((paramValue));
        end
    end

    methods(Static, Access=private)
        function [value,isterminal,direction] = eventTermCond(t,y, targetPitchAngle, steeringModel, bodyInfo)
            ut = t;
            rVect = y(1:3);
            vVect = y(4:6);

            dcm = steeringModel.getBody2InertialDcmAtTime(ut, rVect, vVect, bodyInfo);
            [~,pitchAngle,~] = computeEulerAnglesFromInertialBodyAxes(ut, rVect, vVect, bodyInfo, dcm(:,1), dcm(:,2), dcm(:,3));

            value = pitchAngle - targetPitchAngle;
            isterminal = 1;
            direction = 0;
        end
    end
end


classdef (Abstract) nme_buslink < mp.nm_element %& mp.form_ac

%   MATPOWER
%   Copyright (c) 2021-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end

    methods
        function name = name(obj)
            name = 'buslink';
        end

        function np = np(obj)
            np = 4;     %% this is a 4 port element
        end

        function nz = nz(obj)
            nz = 3;     %% 3 complex non-voltage states per element
        end

        function obj = add_zvars(obj, nm, dm, idx)
            p = idx{1};
            ng = obj.nk;

            if p == 1
                nm.init_indexed_name('zr', 'Plink', {obj.nz});
                nm.init_indexed_name('zi', 'Qlink', {obj.nz});
            end
            nm.add_var('zr', 'Plink', {p}, obj.nk, 0, -Inf, Inf);
            nm.add_var('zi', 'Qlink', {p}, obj.nk, 0, -Inf, Inf);
        end

        function obj = build_params(obj, nm, dm)
            build_params@mp.nm_element(obj, nm, dm);    %% call parent
            I = (dm.base_kva / dm.base_mva / 1000) * speye(obj.nk);
            obj.N = [ repmat(I, 1, obj.nz);
                     -speye(obj.nk * obj.nz) ];
        end

        function [A, b_va, b_vm, Istack_] = voltage_constraints(obj)
            %% form constraint matrices for matching voltages
            nk = obj.nk;

            %% basic constraint matrix for voltage equality (all nodes)
            Istack = repmat(speye(nk), obj.nz, 1);  %% stacked identities
            A = [ Istack -speye(nk * obj.nz) ] * obj.C';
            ang120 = 2*pi/3*ones(nk, 1);

            %% RHS
            b_va = [zeros(nk, 1); ang120; -ang120]; %% angle constraints
            b_vm = zeros(nk*obj.nz, 1);             %% magnitude constraints

            if nargout > 3
                Istack_ = Istack;
            end
        end
    end     %% methods
end         %% classdef


function x0 = randomObjFBASol(model, initArgs)
% Solves an FBA problem with a random objective function
%
% USAGE:
%
%    x0 = randomObjSol(model, initArgs)
%
% INPUTS:
%    model:        COBRA model structure
%    initArgs:     Cell array containing the following data:
%
%                    1.  osenseStr - Maximize ('max') / minimize ('min')
%                    2.  minObjFrac - Minimum initial objective fraction
%                    3.  minObjValue - Minimum initial objective value (opt)
%                        (Default = `minObjFrac*sol.f`)
%
% OUTPUT:
%    x0:           solution of FBA problem
%
% .. Author: - Markus Herrgard

osenseStr = initArgs{1};
minObjFrac = initArgs{2};

if (length(initArgs) < 3)
    solOpt = optimizeCbModel(model,osenseStr);
    model.lb(model.c==1) = minObjFrac*solOpt.f;
else
    model.lb(model.c==1) = initArgs{3};
end

nRxns = length(model.rxns);

model.c = rand(nRxns,1)-0.5;
sol = optimizeCbModel(model,osenseStr);
x0 = sol.x;


function [A,R,w_jk,mu_jk,sigma_jk,extra] = gmm_hu_ex(I, endmembers, options)
%GMM_EX Summary of this function goes here
%   Detailed explanation goes here
if nargin < 3
    options = [];
end

if max(I(:)) > 10 || max(endmembers{1}(:)) > 10
    disp('Warning! I or endmember spectra are not in the range 0 - 1.');
end

if class(I) ~= class(endmembers{1})
    disp('Error! I and endmember spectra do not have the same data type');
end

options = insert_param_when_absent(options, 'reduced_dim', 10);
options = insert_param_when_absent(options, 'max_num_comp', 4);
options = insert_param_when_absent(options, 'show_fig', 0);

options = insert_param_when_absent(options, 'fix_w_k', 1);
options = insert_param_when_absent(options, 'fix_mu_jk', 1);
options = insert_param_when_absent(options, 'fix_sigma_jk', 1);

use_predefined_projection_components = parse_param(options, ...
    'use_predefined_projection_components', 0);

[Y_ori,~,rows,cols] = reshape_hsi(I,[]);
M = length(endmembers);

if use_predefined_projection_components
    mapping = options.project_mapping;
    Y = gmm_project(Y_ori, mapping);
    components = options.predefined_components;
    K = components.K;
    w_jk = components.w_jk;
    mu_jk = components.mu_jk;
    sigma_jk = components.sigma_jk;
else
    % project_mode = 'image' or 'endmembers'
    project_mode = parse_param(options,'project_mode','endmembers');

    if strcmp(project_mode, 'image')
        [Y, mapping] = pca(Y_ori, options.reduced_dim);
    elseif strcmp(project_mode, 'endmembers')
        mapping = calc_projection_from_library(endmembers, options.reduced_dim);
        Y = gmm_project(Y_ori, mapping);
    elseif strcmp(project_mode, 'combined')
        % Gives pretty bad results, should figure out a new implemenation
        mapping = calc_projection_from_image_library(Y_ori, endmembers, options.reduced_dim);
        Y = gmm_project(Y_ori, mapping);
    elseif strcmp(project_mode, 'custom')
        mapping = options.project_mapping;
        Y = gmm_project(Y_ori, mapping);
    else
        disp('ERROR: Unknown projection mode');
    end
    options = insert_param_when_absent(options, 'project_mapping', mapping);

    % Y = gmm_project(Y_ori, mapping);
    [K,w_jk,mu_jk,sigma_jk] = estimate_components(endmembers, mapping, options);
end

if options.show_fig
    names = options.names;
    endmember_scatter_plot_end_var(Y,w_jk,mu_jk,sigma_jk,names);
end

options.w_jk = w_jk;
options.mu_jk = mu_jk;
options.sigma_jk = sigma_jk;
options.K = K;

options = insert_param_when_absent(options, 'beta1', 0);
options = insert_param_when_absent(options, 'beta2', 0);
% options = insert_param_when_absent(options, 'convergence_thresh', 0.002);

% no need to project back to the original dimension, gmm_hu will do it.
[A,R,w_jk,mu_jk,sigma_jk,extra] = gmm_hu(I,M,options);

function mapping = calc_projection_from_image_library(Y_ori, endmembers, reduced_dim)
spectra_train = cell2mat(endmembers');
if size(spectra_train,1) > size(Y_ori,1)
    Y_ori = repmat(Y_ori, round(size(spectra_train,1) / size(Y_ori,1)), 1);
end
spectra_train = cat(1, spectra_train, Y_ori);
[~,mapping] = pca(spectra_train, reduced_dim);

function [beta1,beta2] = automatic_params(I,M,options)
init_beta1 = 10;
init_beta2 = 10;

options.fix_w_k = 0;
options.convergence_thresh = 0.1;

w_jk = options.w_jk;

beta1s = 10.^(-5:5)';
beta2s = 10.^(-5:5)';

errs = Inf(length(beta1s), length(beta2s));
% A_errs = Inf(length(beta1s), length(beta2s));

[~,ind1] = min(abs(beta1s - init_beta1));
[~,ind2] = min(abs(beta2s - init_beta2));
while 1
    ind1s = [ind1-1, ind1, ind1+1];
    ind2s = [ind2-1, ind2, ind2+1];
%     ind2s = ind2;
    for i = ind1s
        for j = ind2s
            % only the inner errors will be updated so the current point
            % will not move to the boundary
            if i > 1 && i < length(beta1s) && j > 1 && ...
                    j < length(beta2s) && errs(i,j) == Inf
                options.beta1 = beta1s(i);
                options.beta2 = beta2s(j);
                [A,R,w_jk1,mu_jk,sigma_jk] = gmm_hu(I,M,options);
                title = ['beta1: ',num2str(options.beta1),', beta2: ',num2str(options.beta2)];
                show_abundances(A, rows, cols, title);
%                 A_errs(i,j) = calc_abundance_error(A_gt,A);
                errs(i,j) = mdiff(w_jk,w_jk1);
            end
        end
    end
    if errs(ind1,ind2) <= errs(ind1-1,ind2) && errs(ind1,ind2) <= errs(ind1+1,ind2) ...
            && errs(ind1,ind2) <= errs(ind1,ind2-1) && errs(ind1,ind2) <= errs(ind1,ind2+1)
        break;
    else
        errs1 = errs(ind1-1:ind1+1,ind2-1:ind2+1);
        [~,ind] = min(errs1(:));
        [y,x] = ind2sub([3 3], ind);
        ind1 = ind1 + y - 2;
        ind2 = ind2 + x - 2;
    end
end

beta1 = beta1s(ind1);
beta2 = beta2s(ind2);


classdef mme_branch_opf_acp < mp.mme_branch_opf_ac

%   MATPOWER
%   Copyright (c) 2021-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%         name = 'branch';
%     end

    methods
        function obj = add_constraints(obj, mm, nm, dm, mpopt)
            %% call parent
            add_constraints@mp.mme_branch_opf_ac(obj, mm, nm, dm, mpopt);

            %% branch voltage angle difference limits
            [Aang, lang, uang, iang] = obj.ang_diff_params(...
                    dm, mpopt.opf.ignore_angle_lim);
            if length(iang)
                mm.add_lin_constraint('ang', Aang, lang, uang, {'Va'});
            end
            mm.userdata.ang_diff_constrained_branch_idx = iang;
        end
    end     %% methods
end         %% classdef


classdef EDNARMOEA < ALGORITHM
% <multi/many> <real/integer> <expensive>
% Efficient dropout neural network based AR-MOEA
% delta --- 0.05 --- Threshold of judging the diversity
% wmax  ---   20 --- Number of generations before updating Kriging models
% Ke    ---    3 --- Number of the solutions to be revaluated in each iteration

%------------------------------- Reference --------------------------------
% D. Guo, X. Wang, K. Gao, Y. Jin, J. Ding, and T. Chai. Evolutionary
% optimization of high-dimensional multiobjective and many-objective
% expensive problems assisted by a dropout neural network. IEEE
% Transactions on Systems, Man, and Cybernetics: Systems, 2022, 52(4):
% 2084-2097.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        function main(Algorithm,Problem)
            assert(~isempty(ver('nnet')),'The execution of EDN-ARMOEA requires the Deep Learning Toolbox.');

            %% Parameter setting
            [delta,wmax,Ke] = Algorithm.ParameterSet(0.05,20,3);
            W     = UniformPoint(Problem.N,Problem.M);
            NI    = 11*Problem.D-1;
            P     = UniformPoint(NI,Problem.D,'Latin');
            A     = Problem.Evaluation(repmat(Problem.upper-Problem.lower,NI,1).*P+repmat(Problem.lower,NI,1));
            tr_x  = A.decs;
            tr_y  = A.objs;
            [tr_xx,ps] = mapminmax(tr_x');tr_xx=tr_xx';
            [tr_yy,qs] = mapminmax(tr_y');tr_yy=tr_yy';
            Params.ps  = ps;Params.qs=qs;
            RatioOld   = [];

            %% Train the model
            [net, Params] = trainmodel(tr_xx, tr_yy, Params);

            while Algorithm.NotTerminated(A)
                %% Update the model
                net=updatemodel(tr_xx, tr_yy, Params, net);

                %% Generate the sampling points and random population
                popsize=Problem.N;
                PopDec=repmat(Problem.upper-Problem.lower,popsize,1).*rand(popsize,Problem.D)+repmat(Problem.lower,popsize,1);
                [PopObj, PopMSE]=Estimate(PopDec, net, Params, Problem.M);
                [Archive,RefPoint,Range, Ratio] = UpdateRefPoint(PopObj,W,[]);
                if isempty(RatioOld)
                    RatioOld=Ratio;
                end

                %% Start the interations
                w=1;
                while w < wmax
                    MatingPool = MatingSelection(PopObj,RefPoint,Range);
                    OffspringDec  = OperatorGA(Problem,PopDec(MatingPool,:),{1,20,1,20});
                    [OffspringObj, OffspringMSE] = Estimate(OffspringDec, net, Params, Problem.M);
                    [Archive,RefPoint,Range, Ratio] = UpdateRefPoint([Archive;OffspringObj],W,Range);
                    MediatePopDec=[PopDec;OffspringDec];
                    MediatePopObj=[PopObj;OffspringObj];
                    MediatePopMSE=[PopMSE;OffspringMSE];
                    [Index,Range]       = EnvironmentalSelection(MediatePopObj,RefPoint,Range,popsize);
                    PopDec=MediatePopDec(Index,:);
                    PopObj=MediatePopObj(Index,:);
                    PopMSE=MediatePopMSE(Index,:);
                    w=w+1;
                end
                flag=RatioOld-Ratio<delta;
                PopNew=IndividualSelect(PopDec, PopObj, PopMSE, Ke, flag);
                RatioOld=Ratio;
                New = Problem.Evaluation(PopNew);
                A   = [A,New];
                [tr_x, tr_y]=SelectTrainData(A, 11*Problem.D-1, length(New));
                [tr_xx,ps]=mapminmax(tr_x');tr_xx=tr_xx';
                [tr_yy,qs]=mapminmax(tr_y');tr_yy=tr_yy';
                Params.ps=ps;Params.qs=qs;
            end
        end
    end
end


function model = rmSearchFit_oneGaussian(model, data, params, wProcess, t)
% rmSearchFit_oneGaussian - wrapper for 'fine' one Gaussian fit
%
% model = rmSearchFit_oneGaussian(model, data, params, wProcess, t);
%
% 2008/01 SOD: split of from rmSearchFit.
% 2010/02 SOD: cleanup.

% fminsearch options
searchOptions = params.analysis.fmins.options;
expandRange   = params.analysis.fmins.expandRange;

% convert to double just in case
params.analysis.X = double(params.analysis.X);
params.analysis.Y = double(params.analysis.Y);
params.analysis.allstimimages = double(params.analysis.allstimimages);
data = double(data);

% get starting upper and lower range and reset TolFun
% (raw rss computation (similar to norm) and TolFun adjustments)
[range TolFun] = rmSearchFit_range(params,model,data);

% amount of negative fits
nNegFit  = 0;
vethresh = params.analysis.fmins.vethresh;
trends   = t.trends;
t_id     = t.dcid+1;

%-----------------------------------
% Go for each voxel
%-----------------------------------
progress = 0;tic;
for ii = 1:numel(wProcess),
    % progress monitor (10 dots)
    if floor(ii./numel(wProcess)*10)>progress,
        % print out estimated time left
        if progress==0,
            esttime = toc.*10;
            if floor(esttime./3600)>0,
                fprintf(1,'[%s]:Estimated processing time: %d voxels: %d hours.\n',...
                    mfilename,numel(wProcess),ceil(esttime./3600));
            else
                fprintf(1,'[%s]:Estimated processing time: %d voxels: %d minutes.\n',...
                    mfilename,numel(wProcess),ceil(esttime./60));
            end;
            fprintf(1,'[%s]:Nonlinear optimization (x,y,sigma):',mfilename);
        end;
        fprintf(1,'.');drawnow;
        progress = progress + 1;
    end;

    % volume index
    vi = wProcess(ii);
    vData = data(:,ii);

    % reset tolFun: Precision of evaluation function.
    % We define RMS improvement relative to the initial raw 'no-fit' data
    % RMS. So, 1 means stop if there is less than 1% improvement on the fit:
    % searchOptions = optimset(searchOptions,'tolFun',optimget(params.analysis.fmins.options,'tolFun')./100.*rawrss);
    % optimset and optimget are a little slow so:
    searchOptions.TolFun = TolFun(ii);

    % actual fitting routine
    if searchOptions.MaxIter>0
        outParams = ...
            fmincon(@(x) rmModelSearchFit_oneGaussian(x,vData,...
            params.analysis.X,...
            params.analysis.Y,...
            params.analysis.allstimimages,trends),...
            range.start(:,vi),[],[],[],[],range.lower(:,vi),range.upper(:,vi),...
            @(x) distanceCon(x,range.start(:,vi),range.step(:,vi).*expandRange),searchOptions);
    else
        outParams = range.start(:,vi);
    end

    %[ outParams range.lower(:,vi) range.start(:,vi) range.upper(:,vi)]

    % make RF, prediction and get rss,b
    Xv = params.analysis.X-outParams(1);
    Yv = params.analysis.Y-outParams(2);
    rf = exp( (Yv.*Yv + Xv.*Xv) ./ (-2.*(outParams(3).^2)) );

    % GLU: checked, they are basically the same
    % {
    % rf=rfGaussian2d(XY{1}, XY{2}, rf.sigmaMajor,rf.sigmaMinor,rf.Theta, ...
    %                            rf.Centerx0,rf.Centery0);
    rf2=rfGaussian2d(params.analysis.X, params.analysis.Y, ...
                    outParams(3),outParams(3),0, ...
                               outParams(1),outParams(2));
    %}

    X  = [params.analysis.allstimimages * rf trends];
    b    = pinv(X)*vData;
    rss  = norm(vData-X*b).^2;

    % store results only if the first beta is positive, somehow fmincon
    % outputs negative fits. If the fit is negative keep old (grid) fit. We
    % do adjust the rss, so it won't be accidentally counted as a 'good'
    % fit.
    if b(1)>0,
        model.x0(vi)   = outParams(1);
        model.y0(vi)   = outParams(2);
        model.s(vi)    = outParams(3);
        model.s_major(vi)    = outParams(3);
        model.s_minor(vi)    = outParams(3);
        model.s_theta(vi)    = 0;
        model.rss(vi)  = rss;
        model.b([1 t_id],vi)  = b;
    else
        % change the percent variance explained to be just under the
        % current vethresh. So it counts as a 'coarse'-fit but can still be
        % included in later 'fine'-fits
        model.rss(vi)  = (1-max((vethresh-0.01),0)).*model.rawrss(vi);
        nNegFit = nNegFit + 1;
    end
end

% end time monitor
et  = toc;
if floor(et/3600)>0,
    fprintf(1,'Done [%d hours].\n',ceil(et/3600));
else
    fprintf(1,'Done [%d minutes].\n',ceil(et/60));
end;
fprintf(1,'[%s]:Removed negative fits: %d (%.1f%%).\n',...
    mfilename,nNegFit,nNegFit./numel(wProcess).*100);
return;

%-----------------------------------
% make sure that the pRF can only be moved "step" away from original
% position "startParams" - for the one Gaussian model
function [C, Ceq]=distanceCon(x,startParams,step)
Ceq = [];
dist = x([1 2])-startParams([1 2]);
C = norm(dist) - step;
return;
%-----------------------------------


function [mat_data, dims, folder_analysis] = distribute_data(nam, patch_dims, ...
    w_overlap, memory_size_per_patch, memory_size_to_use, dir_output, filter_kernel)
% divide the field of view into multiple small patches and save the data
% into these small patches individually. There are overlaps between these
% patches.

%% default values
if ~exist(nam, 'file')
    error('File does not exist!');
end
file_name = get_fullname(nam);

if ~exist('patch_dims', 'var')
    patch_dims = [];
end
if ~exist('w_overlap', 'var') || isempty(w_overlap)
    w_overlap = 10;
end
if ~exist('memory_size_per_patch', 'var') || isempty(memory_size_per_patch)
    memory_size_per_patch = 10;
end
if ~exist('memory_size_to_use', 'var') || isempty(memory_size_to_use)
    memory_size_to_use = 30;
end
if ~exist('filter_kernel', 'var') || isempty(filter_kernel)
    filter_kernel = [];
    filter_data = false;
else
    filter_data = true;
end

%% get the data dimension and determine the best way of distributing data
dims = get_data_dimension(file_name);
d1 = dims(1); d2 = dims(2); T = dims(3);

fprintf('\nThe data has %d X %d pixels X %d frames. \nLoading all data (double precision) requires %.3f GB RAM\n\n', d1, d2, T, prod(dims)/(2^27));

max_elements = memory_size_per_patch* (500^3); % x GB data can save x*1000^3/8 dobule numbers.
min_patch_width = 2*w_overlap+3;
max_patch_width = max(round(sqrt(double(round(max_elements/T))))-w_overlap*2, min_patch_width);

if isempty(patch_dims)
    % find the optimial batch size
    patch_dims = [1, 1] * patch_width;
else
    patch_dims(patch_dims< min_patch_width) = min_patch_width;
%     patch_dims(patch_dims>max_patch_width) = max_patch_width;
    if length(patch_dims)==1
        patch_dims = patch_dims * [1,1];
    else
        patch_dims = patch_dims(1:2);
    end
end

patch_dims = reshape(patch_dims, 1, []);
nr_patch = round(d1/patch_dims(1));
nc_patch = round(d2/patch_dims(2));
if nr_patch <= 1
    patch_idx_r = [1, d1];
else
    patch_idx_r = ceil(linspace(1, d1, nr_patch+1));
    patch_idx_r(end) = d1;
    if diff(patch_idx_r(1:2))<min_patch_width
        patch_idx_r = 1:min_patch_width:d1;
        patch_idx_r(end) = d1;
    end
end
nr_patch = length(patch_idx_r) - 1;

if nc_patch <= 1
    patch_idx_c = [1, d2];
else
    patch_idx_c = ceil(linspace(1, d2, nc_patch+1));
    if diff(patch_idx_c(1:2))<min_patch_width
        patch_idx_c = 1:min_patch_width:d2;
        patch_idx_c(end) = d2;
    end
end
nc_patch = length(patch_idx_c) - 1;

fprintf('The FOV is divided into %d X %d patches. \nEach patch has %d X %d pixels. \n',...
    nr_patch, nc_patch, diff(patch_idx_r(1:2)), diff(patch_idx_c(1:2)));
temp = prod(patch_dims+2*w_overlap)*T/(2^27);
fprintf('It requires %.3f GB RAM for loading data related to each patch. \n\n', temp);
if temp > memory_size_per_patch
    fprintf('You assigned a smaller memory for each patch.\n');
    fprintf('We suggest you process data in batch mode.\nEach batch has frames fewer than %d. \n\n', round(T*memory_size_per_patch/temp));
end

%% indices for dividing the FOV into multiple blocks.
block_idx_r = bsxfun(@plus, patch_idx_r, [-1-w_overlap; w_overlap]);
block_idx_c = bsxfun(@plus, patch_idx_c, [-1-w_overlap; w_overlap]);
block_idx_r = block_idx_r(:);
block_idx_c = block_idx_c(:);
block_idx_r(block_idx_r<1) = 1; block_idx_r(block_idx_r>d1) = d1;
block_idx_c(block_idx_c<1) = 1; block_idx_c(block_idx_c>d2) = d2;
block_idx_r = sort(unique(block_idx_r));
block_idx_c = sort(unique(block_idx_c));
nr_block = length(block_idx_r) - 1;
nc_block = length(block_idx_c) - 1;
% num_blocks = nr_block * nc_block;

%% prepare for distributing the data into multiple patches.
[dir_nm, file_nm, ~] = fileparts(file_name);
if ~exist('dir_output', 'var') || ~exist(dir_output, 'dir')
    dir_output = [dir_nm, filesep];
elseif dir_output(end)~=filesep
    dir_output = dir_output(1:(end-1));
end
folder_analysis = [dir_output, file_nm, '_source_extraction'];

mat_file = [folder_analysis, filesep,...
    sprintf('data_%d_%d_%d.mat', patch_dims(1), patch_dims(2), w_overlap)];

if ~exist(folder_analysis, 'dir')
    mkdir(folder_analysis);
end

% check whether the mat data has been created
if exist(mat_file, 'file')
    mat_data = matfile(mat_file);
    if all(patch_dims==mat_data.patch_dims) && (w_overlap==mat_data.w_overlap)
        fprintf('The data has been divided into multiple patches and saved into \n%s\n\n', mat_file);
        return;
    end
end

% create a mat file and save data info into it.
mat_data = matfile(mat_file, 'Writable', true);
save(mat_file, 'file_name', '-v7.3');
mat_data.patch_idx_r = patch_idx_r;
mat_data.patch_idx_c = patch_idx_c;
mat_data.nr_patch = nr_patch;
mat_data.nc_patch = nc_patch;
mat_data.block_idx_r = block_idx_r;
mat_data.block_idx_c = block_idx_c;
mat_data.nr_block = nr_block;
mat_data.nc_block = nc_block;
mat_data.w_overlap = w_overlap;
mat_data.patch_dims = patch_dims;
mat_data.dims = dims;

% pre-allocate matrices for saving the video data
img = smod_bigread2(file_name,1,1);
default_value = 0*img(1);
temp = whos('img');
mat_data.dtype = temp.class;
for m=1:nr_block
    r0 = block_idx_r(m);
    r1 = block_idx_r(m+1);
    nr = r1-r0+1;
    for n=1:nc_block
        c0 = block_idx_c(n);
        c1 = block_idx_c(n+1);
        nc = c1-c0+1;
        eval(sprintf('mat_data.Y_%d_%d_%d_%d(%d, %d, %d)=default_value;', r0, r1, c0, c1, nr, nc, T));
    end
end

% positions for determing a batch and the minimum block that includes the
% patch
patch_pos = cell(nr_patch, nc_patch);
block_pos = cell(nr_patch, nc_patch);
for m=1:nr_patch
    for n=1:nc_patch
        patch_pos{m, n} = [patch_idx_r(m:(m+1))+[0, -1*(m~=nr_patch)], patch_idx_c(n:(n+1))+[0, -1*(n~=nc_patch)]];
        block_pos{m, n} = [max(1, patch_idx_r(m)-w_overlap-1), min(d1, patch_idx_r(m+1)+w_overlap), ...
            max(1, patch_idx_c(n)-w_overlap-1), min(d2, patch_idx_c(n+1)+w_overlap)];
    end
end
mat_data.patch_pos = patch_pos;
mat_data.block_pos = block_pos;

%% load and distribute data
Tchunk = floor(memory_size_to_use * (500^3) / (d1*d2));
t_start= 0;
fprintf('\n-------- Loading --------\n');
fprintf('Data is being loaded and distributed into multiple small blocks for easy access.\n\n');

while t_start<T
    num2read = min(Tchunk, T-t_start);
    Y = smod_bigread2(file_name, t_start+1, num2read);
    Y(isnan(Y)) = 0;
    temp = Y(1);
    if filter_data
        Y = cast(imfilter(double(Y), filter_kernel, 'replicate'), 'like', temp);
    end
    for m=1:nr_block
        r0 = block_idx_r(m);
        r1 = block_idx_r(m+1);
        nr = r1-r0+1; %#ok<*NASGU>
        for n=1:nc_block
            c0 = block_idx_c(n);
            c1 = block_idx_c(n+1);
            nc = c1-c0+1;
            eval(sprintf('mat_data.Y_%d_%d_%d_%d(1:nr, 1:nc, %d:%d)=Y(%d:%d, %d:%d, :); ', ...
                r0, r1, c0, c1, t_start+1, t_start+num2read, r0, r1, c0, c1));
            fprintf('block(%2d,%2d)/(%d, %d) done\n', m, n, nr_block, nc_block);
        end
    end
    t_start = t_start + num2read;
    fprintf('loaded %d out of %d frames\n', t_start, T);
end
fprintf('\nThe data has been saved into \n%s\n', mat_file);
fprintf('\n-------- Done --------\n');


function [ scores, valid ] = objectClassifier(room_obj, objects, model, ClassNames )
%OBJECT_CLASSIFIER Summary of this function goes here
%   Detailed explanation goes here
% ClassNames = model.ClassNames;
% assert(length(ClassNames)==28, 'Classifier involve class number less than 28.');
% fprintf('object classifier: %d categories\n', length(ClassNames));

room_points = room_obj.out_points_w;
room_xyz = [min(room_points, [], 1) max(room_points, [],  1)];
total_fea_dim = comp_object_3d_feature();
num_object = length(objects);
features = zeros(num_object, total_fea_dim);
valid = true(num_object,1);

for oid = 1:num_object
    obj_points = objects(oid).out_points_w;
    obj_xyz = [min(obj_points, [], 1) max(obj_points, [], 1)];
    test_min = (room_xyz(1:3) - obj_xyz(1:3));
    norm_min = (room_xyz(1:3) - obj_xyz(1:3))./(obj_xyz(4:6)-obj_xyz(1:3)+0.00001);
    test_max = (obj_xyz(4:6) - room_xyz(4:6));
    norm_max = (obj_xyz(4:6) - room_xyz(4:6))./(obj_xyz(4:6)-obj_xyz(1:3)+0.00001);
    if any(norm_min>0.2) || any(norm_max>0.2) || any(test_min>20) || any(test_max>20)
        valid(oid) = false;
        continue;
    end

    obj_x = objects(oid).x_w;
    obj_ori_size = obj_x(4:6)';
    obj_angle = obj_x(7);
    features(oid,:) = comp_object_3d_feature(obj_xyz, room_xyz, obj_ori_size, obj_angle);
end

[~,scores,~] = predict(model, features);
if ~exist('ClassNames','var') || isempty(ClassNames)
    ClassNames = model.ClassNames;
end
I = zeros(1,length(ClassNames));
for i = 1:length(ClassNames)
    I(i) = str2double(ClassNames{i});
end
scores(:,I) = scores;

end


function fixedStatus=fixFlatMesh1File(inFileName,outFileName,grayFile)
% function fixedStatus=fixFlatMesh1File(inFileName,outFileName)
% mrFlatMesh v1.0 had a nasty bug : the 3dGlocs of layer 1 gnodes were
% wrong by -1 voxel in all directions (i.e. a node at [1,2,3] was
% given a 3D location of [0,1,2]
% This has been fixed in v1.5 upwards but old flat.mat files need to be fixed.
% This routine reads in a flat.mat file and tries to fix it by adding 1 to all the layer 1 gLocs3ds
% This is not simple because the layer information has been lost by this point. However,
% infoStr.grayFile should contain the name of the gray file that was used to
% make the flat.mat file. This gray file can be used to identify l1 gNodes.
% If it doesn't exist, the user is prompted to browse for a gray file.
% You can enter this routine with no parameters in which case you'll be asked
% to browse for the input and output files as well
%
% Output files contain an extra field in the infoStr: gloc3d_fixed (==indices of fixed nodes if the fix was successful, 0 otherwise)

if (~exist('inFileName','var'))
    [inFileName,inPathName]=uigetfile('','Locate a flat file');
    inFileName=[inPathName,inFileName];
end

flatFile=load(inFileName);

if (~isfield(flatFile,'gLocs3d'))
    error('No gLocs3d in this file. Can''t go on');

end

gLocs3d=flatFile.gLocs3d;

if (~isfield(flatFile,'infoStr'))
    disp('Warning - no infoStr field found.');
    thisInfo='';
else
    thisInfo=flatFile.infoStr;
end

% Check version information on this file to see if it needs to be fixed.
if (isfield(thisInfo,'Version'))
    if (thisInfo.Version>1.5)
        disp('This file is generated by mrFlatMesh > 1.5. It does not need to be fixed.');
        return;
    end
else
    disp('No version info in file. It may need fixing');
end

% Okay, try to load in the gray file

grayFileName=thisInfo.grayFile;
disp('Attempting to load in the gray file that this flat.mat was made from..');
[nodes, edges, vSize] = readGrayGraph(grayFileName);
if (~nodes & ~edges & ~vSize) % This happens when the file could not be read
    disp(['Failed to read the gray file: ',grayFileName]);
    disp('This may be because you are running on a different platform. Or the gray file may have moved.');
    disp('Try to locate it now....');
    [grayFileName,grayPathName]=uigetfile('','Locate a gray file');
    grayFileName=[grayPathName,grayFileName];
    if (~grayFileName)
        disp('Exiting');
        return;
    else % if a gray file was selected
        % try to load this in..
        [nodes, edges, vSize] = readGrayGraph(grayFileName);
        if (~nodes & ~edges & ~vSize) % This happens when the file could not be read
            error ('Could not read this gray file');
        end % endif bad gray file read
    end % endif gray file selected with uigetfile
end % endif couldn't load the gray file from the infoStr

% We now have nodes, edges, vSize
% nodes(6,:) give the layer...
l1NodeIndices=find(nodes(6,:)==1);
l1NodeCoords=nodes(1:3,l1NodeIndices);
% We now have the coordinates of the l1 nodes in the full gray. We need to know
% which of these are also in gLocs3d

% Note that this isn't as simple as it sounds: we can subtract [1 1 1] from nodes and then
% do an intersection with gLocs3d but we're also going to catch some l2,3,4 nodes as well
% The only thing  that saves us is that we know that gLocs3d was created by concatenating
% l1,l2,l3,l4 so we know that all the l1 nodes should be in a contiguous block at the
% start. We might get a few errors at the end of the block though.
%
% First add 1 to all of gLocs3d
gLocsInc3d=gLocs3d+1;

% Now use sub2ind to prepare for the intersect
maxDim=max([gLocsInc3d(:);l1NodeCoords(:)]);
gLocsIncInd=sub2ind([maxDim,maxDim,maxDim],gLocsInc3d(:,1),gLocsInc3d(:,2),gLocsInc3d(:,3));
l1NodeInd=sub2ind([maxDim,maxDim,maxDim],l1NodeCoords(1,:),l1NodeCoords(2,:),l1NodeCoords(3,:));

% Find candidate l1nodes
[candidateL1Nodes,indAB,indBA]=intersect(gLocsIncInd,l1NodeInd);

% This returns the nodes that have the same locations in the gray file and the flat gLocs3d
% indAB is an index vector such that candidateL1Nodes=gLocsIncInd(indAB)
% indBA is an index such that candiadateL1Nodes=l1NodeInd(indBA)
% So: indAB should contain a contiguous run from 1:(numL1GNodes) where numL1GNodes is the number of l1GNodes
% it may also contain extra entries where it intersected with other random l2,l3,l4 nodes

% We only want the initial, contiguous indices.
indAB=indAB(:); % Make sure
indABPlus1=shift(indAB,[1,0]); % Circular shift the entries up by 1
diffAB=indAB-indABPlus1; % This will be 1 for the first set of contiguous entries
endofBlock=find(diffAB~=1);
endofBLock=endofBlock(1);

% We're almost done :)
gLocs3d(1:endOfBlock,:)=gLocs3d(1:endOfBlock)+1;
% TOTO Mark field to say that we've fixed it.
% Save out the new flat file


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
% Artificial example motivated by Gary Christensen
%==============================================================================

viewPara = { 'viewImage','viewImage2D','colormap',flipud(gray(256))};
imgPara  = {'imgModel','splineInter','regularizer','moments','theta',1};
traPara  = {'trafo','affine2D'};
disPara  = {'distance','SSD'};
regPara  = {'regularizer','mbHyperElastic','alpha',1,...
  'alphaLength',1000,'alphaArea',0,'alphaVolume',500};

expfile = jpgs2data('','disc.jpg','c.jpg', ...
  'omega',[0,1,0,1],'m',[128,128],...
  'viewPara',viewPara,'imgPara',imgPara);

save(expfile,'-append','viewPara','imgPara','traPara','disPara','regPara');
checkDataFile
%==============================================================================


function [dat,nvox] = iimg_cluster_extent(dat,volInfo,k)
% Apply a cluster size threshold to a series of index image data vectors
% (each img is one column)
% given volInfo (must be created with iimg_read_img, with extended output)
%
% :Usage:
% ::
%
%     [dat,nvox] = iimg_cluster_extent(dat,volInfo,k)
%
% :Inputs:
%
%   **dat:**
%        may be an indexed image of all image values or only those in mask
%        defined by volInfo

if isempty(k) || k < 2, nvox = []; return, end % do nothing if extent threshold

if size(dat,1) == volInfo.nvox
    dattype = 'full';
elseif size(dat,1) == volInfo.n_inmask
    dattype = 'masked';
else error('data vector does not match size of image in volInfo!')
end

switch dattype
    case 'full', [clindx,nvox] = iimg_cluster_index(dat(volInfo.wh_inmask, :), volInfo.xyzlist', k);
    case 'masked', [clindx,nvox] = iimg_cluster_index(dat,volInfo.xyzlist',k);
end

switch dattype
    case 'full'
        for i = 1:size(dat,2)
            clindx2 = zeros(volInfo.nvox,1);    % put in original index dims
            clindx2(volInfo.wh_inmask) = clindx(:,i);
            dat(:,i) = dat(:,i) .* (clindx2 > 0);
        end

    case 'masked'
        dat = dat .* (clindx > 0);
end

return


%% A Simple and Robust Vertical Handoff Algorithm for HeterogeneousWireless Mobile Networks
%   Function Parameters:
%   C=cost of Ith network      S=Security     P=Power
%   D = Network Conditions     F= Network Performance
%   V = Velocity of MN         T= Estimated Time MN will stay in the
%                                   network coverage
%   NS = Network Set of eligible candidates for VHO
%   N = Number of Networks Presently available for evaluation.
%   lambda = mean number of request arrivals per unit time
%   mu = mean number of calls serviced per unit time
%   wx = weight function of the 'x' parameter for evaluating EVHDF
%
% Take as input from user the various network parameters for each network
% under consideration.
%
%   Reference: A Simple and Robust Vertical Handoff Algorithm for
%   Heterogenous Wireless Mobile Networks
%   Paper Authors: Daojing He, Caixia Chi, Sammy Chan, Chun Chen, Jiajun Bu,
%   Mingjian Yin.
%   Wireless Pers Commun DOI 10.1007/s11277-010-9922-x
%
%   Code Author: Anshul Thakur
%   Contact: anshulthakurjourneyendless@gmail.com
%   Created: 4/4/2011
%   Copyright Owner: Anshul Thakur

%% Note that the code that has been commented out are of the various
% parameters that the author did not consider for his evaluation. User may
% uncomment the necessary part to include more parameters in their
% evaluation
function code_modified()
%This section of code takes in various parameters of the different networks
%between which decision of a handoff is to be made.
fprintf('\nThe number of networks under evaluation N: \n')
N=input('=');
b=zeros(1,N);
RSS=zeros(1,N);
%V=zeros(1,N);
T=zeros(1,N);
%P=zeros(1,N);
%C=zeros(1,N);
%fj=zeros(1,N);
%wc=zeros(1,N);
%ws=zeros(1,N);
%wf=zeros(1,N);
wp=zeros(1,N);
wd=zeros(1,N);
M=zeros(1,N);
lambda=zeros(1,N);
mu=zeros(1,N);
pj=zeros(1,N);
NL=0;
fprintf('\nEnter the threshold values of various parameters when prompted.\n');
    bi=input('Threshold Current Available Bandwidth: ');
    RSSi=input('Threshold Received Signal Strength:  ');
    %Vi=input('Threshold Velocity of Mobile Station:  ');
    Ti=input('Threshold Estimated Time MS will be in present network:  ');
    %Pi=input('Threshold Battery Power of MS  :');
    %Ci=input('Threshold Cost of Network to MS  :');
for i=1:N
    fprintf('Enter the values for the network number %d when prompted.\n', i);
    if(i==1)
        fprintf('Enter the values of the currently connected network\n');
    end
    b(1,i)=input('Current Available Bandwidth: ');
    RSS(1,i)=input('Received Signal Strength:  ');
    %V(1,i)=input('Velocity of Mobile Station:  ');
    T(1,i)=input('Estimated Time MS will be in present network:  ');
    %P(1,i)=input('Battery Power of MS  :');
    %C(1,i)=input('Cost of Network to MS  :');
    %s(1,i)=input('Security level in Network    :');
    pj(1,i)=input('Power Dissipation in Network  :');
    %fj(1,i)=input('Network Performance Parameter of Network    :');
    lambda(1,i)=input('Mean number of request arrivals per unit time    :');
    mu(1,i)=input('Mean number of calls serviced per unit time  :');
    fprintf('\n \t Enter the Network Dependent Weights to the following parameters\n');
    %wc(1,i)=input('Cost of Service:');
    %ws(1,i)=input('Security Parameter:');
    wp(1,i)=input('Power Consumption: ');
    wd(1,i)=input('Network Conditions:  ');
    %wf(1,i)=input('Network Performance     :');

    %% This part evaluates the first step decision function to find the eligible
    % set of networks out of the available networks with values greater
    % than threshold
    %M(1,i)=((b(1,i)-bi)>0)&&((RSS(1,i)-RSSi)>0)&&((V(1,i)-Vi)>0)&&((T(1,i)-Ti)>0)&&((P(1,i)-Pi)>0)&&((C(1,i)-Ci)>0);
    M(1,i)=((b(1,i)-bi)>0)&&((RSS(1,i)-RSSi)>0)&&((T(1,i)-Ti)>0);
    if M(1,i)==1
        NL=NL+1;
    end
end
if(NL==0)
    fprintf('\nNo eligible networks found. Remain Connected to existing network itself\n');
else
%% Decision making when Network list has some networks in it
    NS=zeros(1,NL);
    hi=zeros(1,NL);
    EQ=zeros(1,NL);
    Dj=zeros(1,NL);
   x=1;
   for i=1:N
        if M(1,i)~=0
            NS(1,x)=i;
            x=x+1;
        end
   end
   if ((NL==1)&&(NS(1,1)==1))
       fprintf('\nNo other network is having minimum service quality better than threshold. Stay in same network\n');
   elseif((NL==1)&&(NS(1,1)~=1))
       fprintf('\n Handoff to new network with Network ID %d',NS(1,1));
   else
       fprintf('\nIs the Mobile Node Reource rich or Resource Poor?\n');
       res=input('r for Rich/ p for Poor      ','s');
       if(strcmp(res,'p'))
           if(NS(1,1)==1)
               frpintf('\nNo handoff required for Resource Poor Mobile Node at present\n');
           else
               fprintf('\nPerform Handoff with any of the %d Networks in the pool',NL);
           end
       elseif(strcmp(res,'r'))
           for i=1:NL
               index=NS(1,i);
               hi(1,i)=dyn_cal_prob(lambda(1,index),mu(1,index),b(1,index));
               Dj(1,i)=(b(1,index))/(hi(1,i));
           end
           %% This section evaluates the Extended Vertical Handoff Decision
           %  Function for the network pool previously selected as eligible
           for i=1:NL
               %index=NS(i,i);
               %Ct(1,i)=C(1,index);
               %EQ(1,i)=((wc(1,index)*(1/Ct(1,i)))/min(Ct,[],2))+(ws(1,index)*s(1,index)/max(s,[],2))+(wp(1,index)*pj(1,index)/max(pj,[],2))+(wd(1,index)*Dj(1,i)/max(Dj,[],2))+(wf(1,index)*fj(1,index)/max(fj,[],2));
               %EQ(1,i)=Dj(1,i)/max(Dj,[],2);
               EQ(1,i)=(wp(1,index)*pj(1,index)/max(pj,[],2))+(wd(1,index)*Dj(1,i)/max(Dj,[],2));
           end
           [para,netwrk]=max(EQ,[],2);
           if netwrk==1
               fprintf('\nCurrently selected Network is the best network, no Handoff required\n');
           else
               fprintf('\nPerform handoff with Network %d for best performance\n',NS(netwrk));
           end
       end
   end
    figure;
    subplot(2,1,1);
    stem(NS(1,:),hi(1,:));
    ylabel('New Dynamic Call Blocking Probability');
    xlabel('Network Number');
    title('a.   NDCBP vs Network ');
    subplot(2,1,2);
    stem(NS(1,:),EQ(1,:));
    title('   b.  EVHDF vs Network');
    xlabel('Netowrk');
    ylabel('Extended Vertical Handoff Decision Function');
end
end

%% Function to compute the New Dynamic Call blocking Probability
function hi=dyn_cal_prob(lambda, mu, bi)
    b=(lambda/mu);
    a=(b.^(bi))/factorial(bi);
    sumi=0;
    for n=0:bi
        sumi=sumi+((b.^exp(n))/factorial(n));
    end
    hi=a/sumi;
end


function texture = faceTexture( FV,R,t,s,im)
%FACETEXTURE Summary of this function goes here
%   Detailed explanation goes here

rotpts = R*FV.vertices';
pts2D =[s.*(rotpts(1,:)+t(1)); s.*(rotpts(2,:)+t(2))];
[rows,cols]=meshgrid(1:size(im,2),1:size(im,1));

FV.facevertexcdata = zeros(0);

for col=1:3%size(im,1)+1-
FV.facevertexcdata(:,col) = interp2(rows,cols,im(:,:,col),pts2D(1,:),size(im,1)+1-pts2D(2,:));
end

%non visible texture set to zero
nonVisibleVertices = setdiff(1:length(FV.vertices), visiblevertices(FV, R));
for col=1:3
FV.facevertexcdata(nonVisibleVertices,col) = NaN;
end

texture = FV.facevertexcdata;
end


% -*- INTERNAL UNDOCUMENTED FUNCTION -*-
%
% Copyright (C) 2010 Carlo de Falco
% Copyright (C) 2011 Rafael Vazquez
%
% 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 Octave; see the file COPYING.  If not, see
% <http://www.gnu.org/licenses/>.

function PI = b2nst__ (space, knots, degree, msh)

  U = knots{1};
  V = knots{2};
  dU = degree(1);
  dV = degree(2);

  %% FIXME only odd degree supported at the moment
  if (mod (dU, 2) == 0 || mod (dV, 2) == 0)
   error ('b2nst__: only odd degree supported at the moment')
  end

  mcp = numel (U) - dU - 1;
  ncp = numel (V) - dV - 1;
  UT = U;
  VT = V;
  UT([dU+2 end-dV-1]) = [];
  VT([dV+2 end-dV-1]) = [];

  %% get numbers of shape functions to replace
  ucenter = (dU+1)/2+1;
  vcenter = (dV+1)/2+1;
  aux = setdiff (1:dV+2, vcenter);
  ns = 0;
  for jj = aux
    ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], ucenter, jj);
    ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], mcp+1-ucenter, jj);
  end

  for jj = ncp+1-aux;
    ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], ucenter, jj);
    ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], mcp+1-ucenter, jj);
  end

  %% get numbers of shape functions to remove
  ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], ucenter, vcenter);
  ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], ucenter, ncp+1-vcenter);
  ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], mcp+1-ucenter, ncp+1-vcenter);
  ns=ns+1; rmshp(ns) = sub2ind ([mcp, ncp], mcp+1-ucenter, vcenter);

  nrmshp = numel (rmshp);

  %% construct projection matrix
  P = speye (space.ndof);
  %% remove basis functions to be removed
  P(:, rmshp) = [];

 % uv = [reshape(msh.quad_nodes(1, :, :),[],1), reshape(msh.quad_nodes(2, :, :),[],1)]';
  ns = 0;
  for jj = 1:dV+1
    ns=ns+1; fun{ns} = @(pts) tbasisfun (pts, [dU, dV], ...
                 {U(ucenter+[0:dU+1]), VT(jj+[0:dV+1])});
    ns=ns+1; fun{ns} = @(pts) tbasisfun (pts, [dU, dV], ...
                 {U(ucenter+[0:dU+1]), VT(end+1-jj-[dV+1:-1:0])});
    ns=ns+1; fun{ns} = @(pts) tbasisfun (pts, [dU, dV], ...
                 {U(end-ucenter+1-[dU+1:-1:0]), VT(jj+[0:dV+1])});
    ns=ns+1; fun{ns} = @(pts) tbasisfun (pts, [dU, dV], ...
                 {U(end-ucenter+1-[dU+1:-1:0]), VT(end+1-jj-[dV+1:-1:0])});
  end

% Computation of the projection
%  We cannot use the op_f_v_tp operator, because our function handles fun{jj}
%  are for points in the parametric domain, not in the physical domain
  M = op_u_v_tp (space, space, msh);

  rhs = zeros (space.ndof, ns);
  for iel = 1:msh.nel_dir(1)
    msh_col = msh_evaluate_col (msh, iel);
    sp_col  = sp_evaluate_col (space, msh_col, 'gradient', false);
    uv = [reshape(msh_col.quad_nodes(1,:,:),[],1), reshape(msh_col.quad_nodes(2,:,:),[],1)]';
    for jj = 1:ns
      rhs(:,jj) = rhs(:,jj) + op_f_v (sp_col, msh_col, ...
                               reshape (fun{jj}(uv), msh_col.nqn, msh_col.nel));
    end
  end

  for jj = 1:ns
    PI(:, jj) = M \ rhs(:,jj);
%    PI(:, jj) = M \ op_f_v_tp (space, msh, reshape (fun(:,jj), size (msh.quad_weights)));
  end

  PI = [P PI];

end


function [Psi, logQ] = RestrictedGibbsScan_Merge( Psi, data_struct, hyperparams, model, TargetPsi )

featIDs = Psi.activeFeatIDs;
objIDs = find( sum( Psi.F(:, featIDs ) , 2 ) > 0 )';

logQ = struct( 'z', 0, 'TS', 0,'theta', 0, 'F', 0, 'all', 0 );

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

[Psi.stateSeq, logQ.z] = sampleStateSeq_RGS( Psi.F, Psi.stateSeq, Psi.TS, Psi.theta, data_struct, model, objIDs, TargetPsi );
[Psi.TS, logQ.TS] = sampleTransParams_RGS( Psi.F, Psi.stateSeq, Psi.TS, hyperparams, model, objIDs, TargetPsi);
[Psi.theta, logQ.theta] = sampleTheta_RGS( Psi.F, Psi.stateSeq, Psi.theta, data_struct, model, featIDs , TargetPsi);

logQ.all = logQ.F + logQ.theta + logQ.TS + logQ.z;


function [GAmp,GTime]=GzCartesian(p)

global VCtl;
global VObj;
global VVar;

t1Start=p.t1Start; %ms
t1End=p.t1End; %ms
t2Start=p.t2Start;
t2End=p.t2End;
tRamp=p.tRamp;
Gz1Sign=p.Gz1Sign;
Gz2Sign=p.Gz2Sign;
% GzOrder=p.GzOrder;
Duplicates=max(1,p.Duplicates);
DupSpacing=max(0,p.DupSpacing);

% if strcmp(GzOrder,'centric')
%     if VVar.SliceCount==1 & VVar.PhaseCount==1
%        SliceCount = (-1)^rem(VVar.SliceCount-1,2)*(VVar.SliceCount-1);
%        VVar.SliceCountTmp = 0;
%     elseif VVar.PhaseCount~=1
%        SliceCount = VVar.SliceCountTmp;
%     else
%        SliceCount = (-1)^rem(VVar.SliceCount-1,2)*(VVar.SliceCount-1) + VVar.SliceCountTmp;
%        VVar.SliceCountTmp = SliceCount;
%     end
% elseif strcmp(GzOrder,'sequential')
%     SliceCount = VVar.SliceCount-floor(VCtl.SliceNum/2)-1;
% end

% phase encoding
GzdG=1/((VObj.Gyro/(2*pi))*(t1End-t1Start)*VCtl.FOVSlice);
[GAmp1,GTime1]=StdTrap(t1Start-tRamp, ...
                       t1End+tRamp,   ...
                       t1Start,               ...
                       t1End,                 ...
                       (VVar.SliceCount-floor(VCtl.SliceNum/2)-1)*GzdG*Gz1Sign,2,2,2); % use floor to make Kz = 0 when VCtl.SliceNum=1
% rephasing
GzdG=1/((VObj.Gyro/(2*pi))*(t2End-t2Start)*VCtl.FOVSlice);
[GAmp2,GTime2]=StdTrap(t2Start-tRamp, ...
                       t2End+tRamp,   ...
                       t2Start,               ...
                       t2End,                 ...
                       (VVar.SliceCount-floor(VCtl.SliceNum/2)-1)*GzdG*Gz2Sign,2,2,2);

GAmp=GAmp1;
GTime=GTime1;

if Gz2Sign~=0
    GAmp=[GAmp, GAmp2];
    GTime=[GTime, GTime2];
end

[GTime,m,n]=unique(GTime);
GAmp=GAmp(m);

% Create Duplicates
if Duplicates~=1 & DupSpacing ~=0
    GAmp=repmat(GAmp,[1 Duplicates]);
    TimeOffset = repmat(0:DupSpacing:(Duplicates-1)*DupSpacing,[length(GTime) 1]);
    GTime=repmat(GTime,[1 Duplicates]) + (TimeOffset(:))';
end

end


From fessler@eecs.umich.edu Thu Jun  1 16:56 EDT 2000
To: millsk@engin.umich.edu
Subject: ml-em
Cc: fessler@eecs.umich.edu
Content-Type: text
Content-Length: 539

function f = mlem(f, g, h)

if nargin < 3
	ftrue = zeros(11); ftrue(3:5,4:7) = 1; ftrue(4,5) = 0;
	h = ones(3,3);
	g = conv2(ftrue, h, 'same');
	g = g + 0.1 * randn(size(g));
	g = max(g, 0);

	f = g;
	imagesc(f), drawnow
	for ii=1:100
		f = mlem(f, g, h);
		imagesc(f), drawnow
	end
return
end

if any(g < 0), error 'need nonnegative data', end
gp = conv2(f, h, 'same');
if any(g > 0 & ~gp), error 'model mismatch', end
ratio = g ./ (gp + eps * (gp==0));

sens = conv2(ones(size(f)), h, 'same');
f = f .* conv2(ratio, h, 'same') ./ sens;


% Fig. 6.57a   Feedback Control of Dynamic Systems, 5e
%             Franklin, Powell, Emami
%
% response comparison of continuous and digital control step.

clear all;
close all;

sim('fig6_57c')
r=[1 1];   %reference input
t=[0 5];
plot(t,r,'r')
hold on
plot(ycd(:,1),ycd(:,2))
plot(ycd(:,1),ycd(:,3),'m:')
title('Figure 6.57(a) Step Responses of Digital and Continuous Controllers')
ylabel('y')
xlabel('Time (sec)')
text(1.1,1.06, '\leftarrow continuous  controller')
text(.7,1.23, '\leftarrow digital  controller')
grid
hold off


%--- help for dsge/forecast_real_time ---
%
%  Forecast from each point in time
%
%  ::
%
%     [ts_fkst,ts_rmse,rmse,Updates]=forecast_real_time(obj)
%     [ts_fkst,ts_rmse,rmse,Updates]=forecast_real_time(obj,varargin)
%
%  Args:
%
%     obj (dsge | svar | rfvar): model object
%     varargin : valid optional inputs coming in pairs. The main inputs
%       of interest for changing the default behavior are:
%
%       - **forecast_rt_nsteps** [integer] : number of periods ahead
%
%  Returns:
%     :
%
%     - **ts_fkst** [struct] : fields are forecasts in the form of ts objects
%       for the different endogenous variables
%
%     - **ts_rmse** [ts|struct] : if only one object is processed, the output
%       is a ts. If instead several objects are processed, fields are RMSEs in
%       the form of ts objects for the different endogenous variables
%
%     - **rmse** [matrix] : RMSEs for the different endogenous variables
%
%     - **Updates** [struct] : fields are the updated (in a filtering sense) in
%       the form of ts objects for the different endogenous variables
%
%  See also:
%     - plot_real_time
%
%