%     Steffen Urban email: steffen.urban@kit.edu
%     Copyright (C) 2014  Steffen Urban
%
%     This program is free software; you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation; either version 2 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License along
%     with this program; if not, write to the Free Software Foundation, Inc.,
%     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

% 04.03.2014 by Steffen Urban
% this is a modified file from
% Davide Scaramuzzas Toolbox OcamCalib
% original filename: click_calib.m

function click_calibUrban(calib_data)

calib_data.calibrated = 0; %this flag is - when the camera has not yet been calibrated

if isempty(calib_data.n_ima),
    data_calib(calib_data);
end;

check_active_images(calib_data);

if isempty(calib_data.I{calib_data.ind_active(1)}),
    ima_read_calib(calib_data);
    if isempty(calib_data.ind_read),
        disp('Cannot extract corners without images');
        return;
    end;
end;

fprintf(1,'\nExtraction of the grid corners on the images\n');

if isempty(calib_data.map), calib_data.map = gray(256); end;

if ~isempty(calib_data.dX),
    dX_default = calib_data.dX;
end;

if ~isempty(calib_data.dY),
    dY_default = calib_data.dY;
end;

if ~isempty(calib_data.n_sq_x),
    n_sq_x_default = calib_data.n_sq_x;
end;

if ~isempty(calib_data.n_sq_y),
    n_sq_y_default = calib_data.n_sq_y;
end;

if ~isempty(calib_data.taylor_order),
    calib_data.taylor_order_default = calib_data.taylor_order;
end;

if ~exist('dX_default')|~exist('dY_default');
    dX_default = 30;
    dY_default = 30;
end;

if ~exist('n_sq_x_default')|~exist('n_sq_y_default'),
    n_sq_x_default = 10;
    n_sq_y_default = 10;
end;

if ~exist('wintx_default')|~exist('winty_default'),
    wintx_default = max(round(calib_data.ocam_model.width/128),round(calib_data.ocam_model.height/96));
    winty_default = wintx_default;
    clear wintx winty
end;

if ~exist('xc_default'),
    xc_default = round(calib_data.ocam_model.height/2);
end;

if ~exist('yc_default'),
    yc_default = round(calib_data.ocam_model.width/2);
end;

if ~exist('taylor_order_default')
    calib_data.taylor_order_default=4;
end;

if ~exist('wintx') | ~exist('winty'),
    for kk = 1:calib_data.n_ima,
        eval(['clear wintx_' num2str(kk)]);
        eval(['clear winty_' num2str(kk)]);
    end;

end;

if ~exist('dont_ask'),
    dont_ask = 0;
end;

if ~isempty(calib_data.ima_proc)
    fprintf(1,'\nCurrently, corners have been extracted for the following image(s): %s\n',num2str(calib_data.ima_proc));
    suppress_image = input('  Do you want to suppress the current image(s) ([] = no, other = yes)? ','s');
    if isempty(suppress_image),
        ima_numbers = input('Type a vector containing the Images to add (e.g. [1 2 3]) = ');
        for i=ima_numbers
            if ~isempty(find(calib_data.ima_proc==i)),
                fprintf(1,'\nyou have already extracted corners from image %d',i);
                replace_image = input(', are you sure you want to replace this image ([] = yes, other = no)?\n','s');
                if isempty(replace_image)
                    calib_data.ima_proc=calib_data.ima_proc(find(calib_data.ima_proc~=i));
                else
                    ima_numbers(find(ima_numbers==i))=0;
                end
            end
        end
        ima_numbers= ima_numbers(find(ima_numbers~=0));
    else
        calib_data.ima_proc=[];
        ima_numbers=[];
        answer = input('\nType the images you want to process (e.g. [1 2 3], [] = all images) = ');
        if isempty(answer)
            ima_numbers = 1:calib_data.n_ima;
        else
            ima_numbers=answer;
        end
    end;
else
    answer=input('\nType the images you want to process (e.g. [1 2 3], [] = all images) = ');
    if isempty(answer)
        ima_numbers = 1:calib_data.n_ima;
    else
        ima_numbers=answer;
    end
end;

manual_squares=1;

if manual_squares,
    calib_data.n_sq_x = input(['Number of squares along the X direction ([]=' num2str(n_sq_x_default) ') = ']); %6
    if isempty(calib_data.n_sq_x), calib_data.n_sq_x = n_sq_x_default; end;
    calib_data.n_sq_y = input(['Number of squares along the Y direction ([]=' num2str(n_sq_y_default) ') = ']); %6
    if isempty(calib_data.n_sq_y), calib_data.n_sq_y = n_sq_y_default; end;
end;

num_points=(calib_data.n_sq_x+1)*(calib_data.n_sq_y+1);

n_sq_x_default = calib_data.n_sq_x;
n_sq_y_default = calib_data.n_sq_y;

if (isempty(calib_data.dX))|(isempty(calib_data.dY)), % This question is now asked only once
    % Enter the size of each square

    calib_data.dX = input(['Size dX of each square along the X direction ([]=' num2str(dX_default) 'mm) = ']);
    calib_data.dY = input(['Size dY of each square along the Y direction ([]=' num2str(dY_default) 'mm) = ']);
    if isempty(calib_data.dX), calib_data.dX = dX_default; else dX_default = calib_data.dX; end;
    if isempty(calib_data.dY), calib_data.dY = dY_default; else dY_default = calib_data.dY; end;

else

    fprintf(1,['Size of each square along the X direction: dX=' num2str(calib_data.dX) 'mm\n']);
    fprintf(1,['Size of each square along the Y direction: dY=' num2str(calib_data.dY) 'mm   (Note: To reset the size of the squares, clear the variables dX and dY)\n']);
    %fprintf(1,'Note: To reset the size of the squares, clear the variables dX and dY\n');

end;

square_vert_side=calib_data.dX; %mm
square_horiz_side=calib_data.dY; %mm
num_vert_square=calib_data.n_sq_x;
num_horiz_square=calib_data.n_sq_y;

calib_data.ocam_model.xc=input(['X coordinate (along height) of the omnidirectional image center = ([]=' num2str(xc_default) ') = ']);
calib_data.ocam_model.yc=input(['Y coordinate (along width) of the omnidirectional image center = ([]=' num2str(yc_default) ') = ']);
if isempty(calib_data.ocam_model.xc), calib_data.ocam_model.xc = xc_default; else xc_default = calib_data.ocam_model.xc; end;
if isempty(calib_data.ocam_model.yc), calib_data.ocam_model.yc = yc_default; else yc_default = calib_data.ocam_model.yc; end;
% xc=385.48;
% yc=516.36;

fprintf(1,'\nEXTRACTION OF THE GRID CORNERS\n');
fprintf(1,'Do you want to use the automatic image selection\n');
answer=input('or do you want to process the images individually ( [] = automatic, other = individual )? ','s');

if isempty(answer)
    use_video_mode = 1;
    %% ================
    %  added code steffen urban
    use_corner_find = 1;
    %% ================
else
    use_video_mode = 0;
    fprintf(1,'Do you want to use the automatic corner extraction\n');
    answer=input('or do you want to extract all the points manually ( [] = automatic, other = manual )? ','s');

    % If you opted for the AUTOMATIC extraction
    if isempty(answer)
        use_automatic   = 1;
        %% ================
        %  added code steffen urban
        use_corner_find = 1;
        %% ================
    else
        use_automatic = 0;
    end

    fprintf(1,'\n');
    % If you opted for the MANUAL extraction
    if use_automatic == 0 %IF manual Extraction
        answer=input('Do you want your clicking to be assisted by a corner detector ( [] = yes, other = no )? ','s');
        if isempty(answer)
            use_corner_find=1;
            disp('Window size for corner finder (wintx and winty): ');
            calib_data.wintx = input(['wintx ([] = ' num2str(wintx_default) ') = ']);
            if isempty(calib_data.wintx), calib_data.wintx = wintx_default; end;
            calib_data.wintx = round(calib_data.wintx);
            calib_data.winty = input(['winty ([] = ' num2str(winty_default) ') = ']);
            if isempty(calib_data.winty), calib_data.winty = winty_default; end;
            winty = round(calib_data.winty);
            fprintf(1,'Window size = %dx%d\n',2*calib_data.wintx+1,2*calib_data.winty+1);

        else
            %% ================
            %  added code steffen urban
            use_corner_find = 1;
            %% ================
        end
    end
end

%Arranging the pixel of the world
calib_data.Xt=[];
calib_data.Yt=[];
for i=0:calib_data.n_sq_x
    for j=0:calib_data.n_sq_y
        calib_data.Yt=[calib_data.Yt;j*calib_data.dY];
        calib_data.Xt=[calib_data.Xt;i*calib_data.dX];
    end
end

if use_video_mode == 0
    for kk = ima_numbers,
        if ~isempty(calib_data.I{kk})
            if use_automatic == 0 %IF manual extraction
                click_ima_calib(kk,use_corner_find,calib_data);
            else %IF automatic extraction
                click_ima_calib_rufli(kk,use_corner_find,calib_data);
                %click_ima_calib_vladimir
            end
            calib_data.active_images(kk) = 1;
            calib_data.ima_proc= sort([calib_data.ima_proc, kk]);
        end;
    end;
else
    count = 0;
    for kk = ima_numbers

        [callBack, x, y]  = get_checkerboard_cornersUrban(kk,use_corner_find,calib_data);

        if callBack == 1
            count = count + 1;
            calib_data.Xp_abs(:,:,kk) = x;
            calib_data.Yp_abs(:,:,kk) = y;
            calib_data.active_images(kk) = 1;
            calib_data.ima_proc= sort([calib_data.ima_proc, kk]);
        end
    end
end

check_active_images(calib_data);

fprintf(1,'\nCorner extraction finished.\n');

end


function o = symmetrise(o,varargin)
% all crystallographically equivalent orientations

if nargin > 1 && isa(varargin{1},'symmetry')
  CS = varargin{1};
  SS = getClass(varargin(2:end),'symmetry',specimenSymmetry);
else
  CS = o.CS;
  SS = o.SS;
end

if check_option(varargin,'proper')
  CS = CS.properGroup;
  SS = SS.properGroup;
end
o = symmetrise@rotation(o,CS,SS);

if o.antipodal, o = [o;inv(o)]; end

if check_option(varargin,'unique')
  [~,ind] = unique(o,'noSymmetry');
  o = subSet(o,ind);
end


hb_setup();

res = rproc.read('scoresroot', ...
  fullfile(hb_path, 'matlab', 'scores', 'scores_norm_small'));

%%

categories = cellfun(@(a) a(1), res.matching.sequence, 'Uni', false);
res.matching.category = categories;
% Compute the matching scores averages
res.matching_g = varfun(@mean, res.matching, ...
  'GroupingVariables', {'descriptor', 'geom_noise', 'category'}, ...
  'InputVariables', 'ap');

%% Separate the normalisation type and split out of descriptor name

res.verification_e = rproc.postproc_norm(res.verification);
res.matching_ge = rproc.postproc_norm(res.matching_g);
res.retrieval_e = rproc.postproc_norm(res.retrieval);

%% Compute average over the norm splits
res.verification_en = varfun(@mean, res.verification_e, ...
  'GroupingVariables', {'descriptor', 'split', 'negs', 'geom_noise', 'method', 'norm_type'}, ...
  'InputVariables', 'pr_ap');

res.matching_gen = varfun(@mean, res.matching_ge, ...
  'GroupingVariables', {'descriptor', 'geom_noise', 'category', 'norm_type'}, ...
  'InputVariables', 'mean_ap');

res.retrieval_en = varfun(@mean, res.retrieval_e, ...
  'GroupingVariables', {'descriptor', 'split', 'geom_noise', 'method', 'norm_type'}, ...
  'InputVariables', 'map');

%% Pick the best normalisation per descriptor
% Preprocess the results

ver_ = res.verification_en;
ver_(~cellfun(@(a) strcmp(a, 'b'), ver_.split), :) = [];
ver_(~cellfun(@(a) strcmp(a, 'imbalanced'), ver_.method), :) = [];

ver_ = varfun(@mean, ver_, ...
  'GroupingVariables', {'descriptor', 'split', 'norm_type'}, ...
  'InputVariables', 'mean_pr_ap');
ver_.split = []; ver_.GroupCount = [];
ver_ = unstack(ver_, 'mean_mean_pr_ap', 'norm_type');
ver_.Properties.RowNames = ver_.descriptor;
ver_.descriptor = [];

match_ = res.matching_gen;
match_.GroupCount = [];
match_ = varfun(@mean, match_, ...
  'GroupingVariables', {'descriptor', 'norm_type'}, ...
  'InputVariables', 'mean_mean_ap');
match_.GroupCount = [];
match_ = unstack(match_, 'mean_mean_mean_ap', 'norm_type');
match_.Properties.RowNames = match_.descriptor;
match_.descriptor = [];

retr_ = res.retrieval_en;
retr_.GroupCount = [];
retr_(cellfun(@(a) strcmp(a, 'keepquery'), retr_.method), :) = [];
retr_ = varfun(@mean, retr_, ...
  'GroupingVariables', {'descriptor', 'norm_type'}, ...
  'InputVariables', 'mean_map');
retr_.GroupCount = [];
retr_ = unstack(retr_, 'mean_mean_map', 'norm_type');
retr_.Properties.RowNames = retr_.descriptor;
retr_.descriptor = [];

%%
ver_best = max(max(ver_{:, :}));
match_best = max(max(match_{:, :}));
retr_best = max(max(retr_{:, :}));

% Weight the scores relatively to the best score
total_score = ver_;
total_score{:,:} = (ver_{:,:} ./ ver_best + match_{:,:} ./ match_best + retr_{:,:} ./ retr_best) ./ 3;

[~, best_norm] = max(total_score{:,:}, [], 2);
best_norm_name = total_score.Properties.VariableNames(best_norm)';

best_norm = struct('descriptor', total_score.Properties.RowNames, ...
  'normstr', best_norm_name);
best_norm = struct2table(best_norm, 'asArray', true);
%%
writetable(best_norm, fullfile(hb_path, 'matlab', 'data', 'best_normalizations.csv'));


%SerialLink.IKINEM Numerical inverse kinematics by minimization
%
% Q = R.ikinem(T) is the joint coordinates corresponding to the robot
% end-effector pose T which is a homogenenous transform.
%
% Q = R.ikinem(T, Q0, OPTIONS) specifies the initial estimate of the joint
% coordinates.
%
% In all cases if T is 4x4xM it is taken as a homogeneous transform sequence
% and R.ikinem() returns the joint coordinates corresponding to each of the
% transforms in the sequence.  Q is MxN where N is the number of robot joints.
% The initial estimate of Q for each time step is taken as the solution
% from the previous time step.
%
% Options::
% 'pweight',P      weighting on position error norm compared to rotation
%                  error (default 1)
% 'stiffness',S    Stiffness used to impose a smoothness contraint on joint
%                  angles, useful when N is large (default 0)
% 'qlimits'        Enforce joint limits
% 'ilimit',L       Iteration limit (default 1000)
% 'nolm'           Disable Levenberg-Marquadt
%
% Notes::
% - PROTOTYPE CODE UNDER DEVELOPMENT, intended to do numerical inverse kinematics
%   with joint limits
% - The inverse kinematic solution is generally not unique, and
%   depends on the initial guess Q0 (defaults to 0).
% - The function to be minimized is highly nonlinear and the solution is
%   often trapped in a local minimum, adjust Q0 if this happens.
% - The default value of Q0 is zero which is a poor choice for most
%   manipulators (eg. puma560, twolink) since it corresponds to a kinematic
%   singularity.
% - Such a solution is completely general, though much less efficient
%   than specific inverse kinematic solutions derived symbolically, like
%   ikine6s or ikine3.% - Uses Levenberg-Marquadt minimizer LMFsolve if it can be found,
%   if 'nolm' is not given, and 'qlimits' false
% - The error function to be minimized is computed on the norm of the error
%   between current and desired tool pose.  This norm is computed from distances
%   and angles and 'pweight' can be used to scale the position error norm to
%   be congruent with rotation error norm.
% - This approach allows a solution to obtained at a singularity, but
%   the joint angles within the null space are arbitrarily assigned.
% - Joint offsets, if defined, are added to the inverse kinematics to
%   generate Q.
% - Joint limits become explicit contraints if 'qlimits' is set.
%
% See also fminsearch, fmincon, SerialLink.fkine, SerialLink.ikine, tr2angvec.

% Copyright (C) 1993-2017, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

function qt = ikinem(robot, tr, varargin)

    opt.pweight = 1;
    opt.stiffness = 0;
    opt.qlimits = false;
    opt.ilimit = 1000;
    opt.lm = true;
    opt.col = 2;

    [opt,args] = tb_optparse(opt, varargin);

    % check if optional argument is a valid q
    q0 = args{1};
    if numel(q0) ~= robot.n
        error('q0 length must match number of joints in robot');
    end

    for i=1:size(tr,3)
        T = tr(:,:,i);

        if opt.qlimits
            % constrained optimization to handle joint limits
            options = optimset('MaxIter', opt.ilimit);
            qlim = robot.qlim;

            [q, ef, exflag, output] = fmincon( @(x) costfun(x, robot, T, opt), q0, ...
                [], [], [], [], ...
                qlim(:,1), qlim(:,2), ...
                [], options);

            if opt.verbose
                fprintf('final error %f, %d iterations, %d evalations\n', ...
                    ef, output.iterations, output.funcCount);
            end

        else
            % no joint limits, unconstrained optimization
            if exist('LMFsolve') == 2 && opt.lm
                [q, ef, count] = LMFsolve( @(x) costfun(x, robot, T, opt), q0, 'MaxIter', opt.ilimit);
                q = q';
                if opt.verbose
                    fprintf('final error %f, %d iterations\n', ...
                        ef, count);
                end
            else
                options = optimset('MaxIter', opt.ilimit);
                [q, ef, exflag, output] = fminsearch( @(x) costfun(x, robot, T, opt), q0, options);

                if opt.verbose
                    fprintf('final error %f, %d iterations, %d evalations\n', ...
                        ef, output.iterations, output.funcCount);
                end
            end
        end

        qt(i,:) = q;
    end

    if opt.verbose
        robot.fkine(qt)
    end
end

% The cost function, this is the value to be minimized
function E = costfun(q, robot, T, opt)

    Tq = robot.fkine(q);
    % find the pose error in SE(3)
    dT = transl(T) - transl(Tq);

    % translation error
    E = norm(dT) * opt.pweight;

    % rotation error
    %  find dot product of
    dd = dot(T(1:3,opt.col), Tq(1:3,opt.col));
    %E = E + (1 - dd)^2*100000 ;
    E = E + acos(dd)^2*1000 ;

    if opt.stiffness > 0
        % enforce a continuity constraint on joints, minimum bend
        E = E + sum( diff(q).^2 ) * opt.stiffness;
    end
end


% dataset      -> (1=>user data) or (2=>toy example)
% type         -> (1=> Regression model) or (2=>Classification model)
% num_glevel   -> number of hidden nodes in the net (gating levels)
% num_exp      -> number of experts in the net
% branch_fact  -> dimension of the hidden nodes in the net
% cov_dim      -> root node dimension
% res_dim      -> output node dimension
% nodes_info   -> 4 x num_glevel+2 matrix that contain all the info about the nodes:
%                 nodes_info(1,:) = nodes type: (0=>gaussian)or(1=>softmax)or(2=>mlp)
%                 nodes_info(2,:) = nodes size: [cov_dim   num_glevel x branch_fact   res_dim]
%                 nodes_info(3,:) = hidden units number (for mlp nodes)
%                                  |- optimizer iteration number (for softmax & mlp CPD)
%                 nodes_info(4,:) =|- covariance type (for gaussian CPD)->
%                                  | (1=>Full)or(2=>Diagonal)or(3=>Full&Tied)or(4=>Diagonal&Tied)
% fh1 -> Figure: data & decizion boundaries; fh2 -> confusion matrix; fh3 -> LL trace
% test_data    -> test data matrix
% train_data   -> training data matrix
% ntrain       -> size(train_data,2)
% ntest        -> size(test_data,2)
% cases        -> (cell array) training data formatted for the learning engine
% bnet         -> bayesian net before learning
% bnet2        -> bayesian net after learning
% ll           -> log-likelihood before learning
% LL2          -> log-likelihood trace
% onodes       -> obs nodes in bnet & bnet2
% max_em_iter  -> maximum number of interations of the EM algorithm
% train_result -> prediction on the training set (as test_result)
%
% IMPORTANT: CHECK the loading path (lines 64 & 364)
% ----------------------------------------------------------------------------------------------------
% -> pierpaolo_b@hotmail.com   or   -> pampo@interfree.it
% ----------------------------------------------------------------------------------------------------

error('this no longer works with the latest version of BNT')

clear all;
clc;
disp('---------------------------------------------------');
disp('  Hierarchical Mixtures of Experts models builder ');
disp('---------------------------------------------------');
disp(' ')
disp('   Using this script you can build both an HME model')
disp('as in [Wat94] and [Jor94] i.e. with ''softmax'' gating')
disp('nodes and ''gaussian'' ( for regression ) or ''softmax''')
disp('( for classification ) expert node, and its variants')
disp('called ''gated nets'' where we use ''mlp'' models in')
disp('place of a number of ''softmax'' ones [Mor98], [Wei95].')
disp('  You can decide to train and test the model on your')
disp('datasets  or  to evaluate its  performance on  a toy')
disp('example.')
disp(' ')
disp('Reference')
disp('[Mor98] P. Moerland (1998):')
disp('        Localized mixtures of experts. (http://www.idiap.ch/~perry/)')
disp('[Jor94] M.I. Jordan, R.A. Jacobs (1994):')
disp('        HME and the EM algorithm. (http://www.cs.berkeley.edu/~jordan/)')
disp('[Wat94] S.R. Waterhouse, A.J. Robinson (1994):')
disp('        Classification using HME. (http://www.oigeeza.com/steve/)')
disp('[Wei95] A.S. Weigend, M. Mangeas (1995):')
disp('        Nonlinear gated experts for time series.')
disp(' ')

if 0
disp('(See the figure)')
pause(5);
%%%%%WARNING!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
im_path=which('HMEforMatlab.jpg');
fig=imread(im_path, 'jpg');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure('Units','pixels','MenuBar','none','NumberTitle','off', 'Name', 'HME model');
image(fig);
axis image;
axis off;
clear fig;
set(gca,'Position',[0 0 1 1])
disp('(Press any key to continue)')
pause
end

clc
disp('---------------------------------------------------');
disp('              Specify the Architecture             ');
disp('---------------------------------------------------');
disp(' ');
disp('What kind of model do you need?')
disp(' ')
disp('1) Regression ')
disp('2) Classification')
disp(' ')
type=input('1 or 2?: ');
if (isempty(type)|(~ismember(type,[1 2]))), error('Invalid value'); end
clc
disp('----------------------------------------------------');
disp('               Specify the Architecture             ');
disp('----------------------------------------------------');
disp(' ')
disp('Now you have to set the number of experts and gating')
disp('levels in the net.  This script builds only balanced')
disp('hierarchy with the same branching factor (>1)at each')
disp('(gating) level. So remember that: ')
disp(' ')
disp('         num_exp = branch_fact^num_glevel           ')
disp(' ')
disp('with branch_fact >=2.')
disp('You can also set to zeros the number of gating level')
disp('in order to obtain a classical GLM model.           ')
disp(' ')
disp('----------------------------------------------------');
disp(' ')
num_glevel=input('Insert the number of gating levels {0,...,20}: ');
if (isempty(num_glevel)|(~ismember(num_glevel,[0:20]))), error('Invalid value'); end
nodes_info=zeros(4,num_glevel+2);
if num_glevel>0, %------------------------------------------------------------------------------------
    for i=2:num_glevel+1,
        clc
        disp('----------------------------------------------------');
        disp('               Specify the Architecture             ');
        disp('----------------------------------------------------');
        disp(' ')
        disp(['-> Gating network ', num2str(i-1), ' is a: '])
        disp(' ')
        disp('   1) Softmax model');
        disp('   2) Two layer perceptron model')
        disp(' ')
        nodes_info(1,i)=input('1 or 2?: ');
        if (isempty(nodes_info(1,i))|(~ismember(nodes_info(1,i),[1 2]))), error('Invalid value'); end
        disp(' ')
        if nodes_info(1,i)==2,
           nodes_info(3,i)=input('Insert the number of units in the hidden layer: ');
           if (isempty(nodes_info(3,i))|(floor(nodes_info(3,i))~=nodes_info(3,i))|(nodes_info(3,i)<=0)),
              error(['Invalid value: ', num2str(nodes_info(3,i)), ' is not a positive integer!']);
           end
           disp(' ')
        end
        nodes_info(4,i)=input('Insert the optimizer iteration number: ');
        if (isempty(nodes_info(4,i))|(floor(nodes_info(4,i))~=nodes_info(4,i))|(nodes_info(4,i)<=0)),
           error(['Invalid value: ', num2str(nodes_info(4,i)), ' is not a positive integer!']);
        end
    end
    clc
    disp('---------------------------------------------------------');
    disp('                 Specify the Architecture                ');
    disp('---------------------------------------------------------');
    disp(' ')
    disp('Now you have to set the number  of experts in the network');
    disp('The value will be adjusted in order to obtain a hierarchy');
    disp('as said above.')
    disp(' ');
    num_exp=input(['Insert the approximative number of experts (>=', num2str(2^num_glevel), '): ']);
    if (isempty(num_exp)|(num_exp<=0)|(num_exp<2^num_glevel)),
        error('Invalid value');
    end
    app1=0; base=2;
    while app1<num_exp,
        app1=base^num_glevel;
        base=base+1;
    end
    app2=(base-2)^num_glevel;
    branch_fact=base-1;
    if app2>=(2^num_glevel)&(abs(app2-num_exp)<abs(app1-num_exp)),
        branch_fact=base-2;
    end
    clear app1 app2 base;
    disp(' ')
    disp(['The effective number of experts in the net is: ', num2str(branch_fact^num_glevel), '.'])
    disp(' ');
else
    clc
    disp('---------------------------------------------------------');
    disp('        Specify the Architecture (GLM model)             ');
    disp('---------------------------------------------------------');
    disp(' ')
end % END of: if num_glevel>0-------------------------------------------------------------------------

if type==2,
    disp(['-> Expert node is a: '])
    disp(' ')
    disp('   1) Softmax model');
    disp('   2) Two layer perceptron model')
    disp(' ')
    nodes_info(1,end)=input('1 or 2?: ');
    if (isempty(nodes_info(1,end))|(~ismember(nodes_info(1,end),[1 2]))),
        error('Invalid value');
    end
    disp(' ')
    if nodes_info(1,end)==2,
       nodes_info(3,end)=input('Insert the number of units in the hidden layer: ');
       if (isempty(nodes_info(3,end))|(floor(nodes_info(3,end))~=nodes_info(3,end))|(nodes_info(3,end)<=0)),
           error(['Invalid value: ', num2str(nodes_info(3,end)), ' is not a positive integer!']);
       end
       disp(' ')
    end
    nodes_info(4,end)=input('Insert the optimizer iteration number: ');
    if (isempty(nodes_info(4,end))|(floor(nodes_info(4,end))~=nodes_info(4,end))|(nodes_info(4,end)<=0)),
        error(['Invalid value: ', num2str(nodes_info(4,end)), ' is not a positive integer!']);
    end
elseif type==1,
    disp('What kind of covariance matrix structure do you want?')
    disp(' ')
    disp('   1) Full');
    disp('   2) Diagonal')
    disp('   3) Full & Tied');
    disp('   4) Diagonal & Tied')

    disp(' ')
    nodes_info(4,end)=input('1, 2, 3 or 4?: ');
    if (isempty(nodes_info(4,end))|(~ismember(nodes_info(4,end),[1 2 3 4]))),
        error('Invalid value');
    end
end
clc
disp('----------------------------------------------------');
disp('                    Specify the Input               ');
disp('----------------------------------------------------');
disp(' ')
disp('Do you want to...')
disp(' ')
disp('1) ...use your own dataset?')
disp('2) ...apply the model on a toy example?')
disp(' ')
dataset=input('1 or 2?: ');
if (isempty(dataset)|(~ismember(dataset,[1 2]))), error('Invalid value'); end
if dataset==1,
    if type==1,
        clc
        disp('-------------------------------------------------------');
        disp('        Specify the Input - Regression problem         ');
        disp('-------------------------------------------------------');
        disp(' ')
        disp('Be sure that each row of your data matrix is an example');
        disp('with the covariate values that precede the respond ones')
        disp(' ')
        disp('-------------------------------------------------------');
        disp(' ')
        cov_dim=input('Insert the covariate space dimension: ');
        if (isempty(cov_dim)|(floor(cov_dim)~=cov_dim)|(cov_dim<=0)),
          error(['Invalid value: ', num2str(cov_dim), ' is not a positive integer!']);
        end
        disp(' ')
        res_dim=input('Insert the dimension of the respond variable: ');
        if (isempty(res_dim)|(floor(res_dim)~=res_dim)|(res_dim<=0)),
            error(['Invalid value: ', num2str(res_dim), ' is not a positive integer!']);
        end
        disp(' ');
    elseif type==2
        clc
        disp('-------------------------------------------------------');
        disp('      Specify the Input - Classification problem       ');
        disp('-------------------------------------------------------');
        disp(' ')
        disp('Be sure that each row of your data matrix is an example');
        disp('with the covariate values that precede the class labels');
        disp('(integer value >=1).                                   ');
        disp(' ')
        disp('-------------------------------------------------------');
        disp(' ')
        cov_dim=input('Insert the covariate space dimension: ');
        if (isempty(cov_dim)|(floor(cov_dim)~=cov_dim)|(cov_dim<=0)),
          error(['Invalid value: ', num2str(cov_dim), ' is not a positive integer!']);
        end
        disp(' ')
        res_dim=input('Insert the number of classes: ');
        if (isempty(res_dim)|(floor(res_dim)~=res_dim)|(res_dim<=0)),
          error(['Invalid value: ', num2str(res_dim), ' is not a positive integer!']);
        end
        disp(' ')
    end
    % ------------------------------------------------------------------------------------------------
    % Loading training data --------------------------------------------------------------------------
    % ------------------------------------------------------------------------------------------------
    train_path=input('Insert the complete (with extension) path of the training data file:\n >> ','s');
    if isempty(train_path), error('You must specify a data set for training!'); end
    if ~isempty(findstr('.mat',train_path)),
        ap=load(train_path); app=fieldnames(ap); train_data=eval(['ap.', app{1,1}]);
        clear ap app;
    elseif ~isempty(findstr('.txt',train_path)),
        train_data=load(train_path, '-ascii');
    else
        error('Invalid data format: not a .mat or a .txt file')
    end
    if (size(train_data,2)~=cov_dim+res_dim)&(type==1),
        error(['Invalid data matrix size: ', num2str(size(train_data,2)), ' columns rather than ',...
            num2str(cov_dim+res_dim),'!']);
    elseif (size(train_data,2)~=cov_dim+1)&(type==2),
        error(['Invalid data matrix size: ', num2str(size(train_data,2)), ' columns rather than ',...
            num2str(cov_dim+1),'!']);
    elseif (~isempty(find(ismember(intersect([train_data(:,end)' 1:res_dim],...
            train_data(:,end)'),[1:res_dim])==0)))&(type==2),
        error('Invalid class label');
    end
    ntrain=size(train_data,1);
    train_d=train_data(:,1:cov_dim);
    if type==2,
        train_t=zeros(ntrain, res_dim);
        for m=1:res_dim,
            train_t((find(train_data(:,end)==m))',m)=1;
        end
    else
        train_t=train_data(:,cov_dim+1:end);
    end
    disp(' ')
    % ------------------------------------------------------------------------------------------------
    % Loading test data ------------------------------------------------------------------------------
    % ------------------------------------------------------------------------------------------------
    disp('(If you don''t want to specify a test-set press ''return'' only)');
    test_path=input('Insert the complete (with extension) path of the test data file:\n >> ','s');
    if ~isempty(test_path),
        if ~isempty(findstr('.mat',test_path)),
            ap=load(test_path); app=fieldnames(ap); test_data=eval(['ap.', app{1,1}]);
            clear ap app;
        elseif ~isempty(findstr('.txt',test_path)),
            test_data=load(test_path, '-ascii');
        else
            error('Invalid data format: not a .mat or a .txt file')
        end
        if (size(test_data,2)~=cov_dim)&(size(test_data,2)~=cov_dim+res_dim)&(type==1),
            error(['Invalid data matrix size: ', num2str(size(test_data,2)), ' columns rather than ',...
                num2str(cov_dim+res_dim), ' or ', num2str(cov_dim), '!']);
        elseif (size(test_data,2)~=cov_dim)&(size(test_data,2)~=cov_dim+1)&(type==2),
            error(['Invalid data matrix size: ', num2str(size(test_data,2)), ' columns rather than ',...
                num2str(cov_dim+1), ' or ', num2str(cov_dim), '!']);
        elseif (~isempty(find(ismember(intersect([test_data(:,end)' 1:res_dim],...
                test_data(:,end)'),[1:res_dim])==0)))&(type==2)&(size(test_data,2)==cov_dim+1),
            error('Invalid class label');
        end
        ntest=size(test_data,1);
        test_d=test_data(:,1:cov_dim);
        if (type==2)&(size(test_data,2)>cov_dim),
            test_t=zeros(ntest, res_dim);
            for m=1:res_dim,
                test_t((find(test_data(:,end)==m))',m)=1;
            end
        elseif (type==1)&(size(test_data,2)>cov_dim),
            test_t=test_data(:,cov_dim+1:end);
        end
        disp(' ');
    end
else
    clc
    disp('----------------------------------------------------');
    disp('                  Specify the Input                 ');
    disp('----------------------------------------------------');
    disp(' ')
    ntrain = input('Insert the number of examples in training (<500): ');
    if (isempty(ntrain)|(floor(ntrain)~=ntrain)|(ntrain<=0)|(ntrain>500)),
          error(['Invalid value: ', num2str(ntrain), ' is not a positive integer <500!']);
    end
    disp(' ')
    test_path='toy';
    ntest = input('Insert the number of examples in test (<500): ');
    if (isempty(ntest)|(floor(ntest)~=ntest)|(ntest<=0)|(ntest>500)),
          error(['Invalid value: ', num2str(ntest), ' is not a positive integer <500!']);
    end

    if type==2,
        cov_dim=2;
        res_dim=3;
        seed = 42;
        [train_d, ntrain1, ntrain2, train_t]=gen_data(ntrain, seed);
        for m=1:ntrain
            q=[]; q = find(train_t(m,:)==1);
            train_data(m,:)=[train_d(m,:) q];
        end
        [test_d, ntest1, ntest2, test_t]=gen_data(ntest);
        for m=1:ntest
            q=[]; q = find(test_t(m,:)==1);
            test_data(m,:)=[test_d(m,:) q];
        end
    else
        cov_dim=1;
        res_dim=1;
        global HOME
        %%%%%WARNING!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        load([HOME '/examples/static/Misc/mixexp_data.txt'], '-ascii');
        %%%%%WARNING!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        train_data = mixexp_data(1:ntrain, :);
        train_d=train_data(:,1:cov_dim); train_t=train_data(:,cov_dim+1:end);
        test_data = mixexp_data(ntrain+1:ntrain+ntest, :);
        test_d=test_data(:,1:cov_dim);
        if size(test_data,2)>cov_dim,
            test_t=test_data(:,cov_dim+1:end);
        end
    end
end
% Set the nodes dimension-----------------------------------
if num_glevel>0,
    nodes_info(2,2:num_glevel+1)=branch_fact;
end
nodes_info(2,1)=cov_dim; nodes_info(2,end)=res_dim;
%-----------------------------------------------------------
% Prepare the training data for the learning engine---------
%-----------------------------------------------------------
cases = cell(size(nodes_info,2), ntrain);
for m=1:ntrain,
    cases{1,m}=train_data(m,1:cov_dim)';
    cases{end,m}=train_data(m,cov_dim+1:end)';
end
%-----------------------------------------------------------------------------------------------------
[bnet onodes]=hme_topobuilder(nodes_info);
engine = jtree_inf_engine(bnet, onodes);
clc
disp('---------------------------------------------------------------------');
disp('                         L  E  A  R  N  I  N  G                      ');
disp('---------------------------------------------------------------------');
disp(' ')
ll = 0;
for l=1:ntrain
  scritta=['example number: ', int2str(l),'---------------------------------------------'];
  disp(scritta);
  ev = cases(:,l);
  [engine, loglik] = enter_evidence(engine, ev);
  ll = ll + loglik;
end
disp(' ')
disp(['Log-likelihood before learning: ', num2str(ll)]);
disp(' ')
disp('(Press any key to continue)');
pause
%-----------------------------------------------------------
clc
disp('---------------------------------------------------------------------');
disp('                         L  E  A  R  N  I  N  G                      ');
disp('---------------------------------------------------------------------');
disp(' ')
max_em_iter=input('Insert the maximum number of the EM algorithm iterations: ');
if (isempty(max_em_iter)|(floor(max_em_iter)~=max_em_iter)|(max_em_iter<=1)),
          error(['Invalid value: ', num2str(ntest), ' is not a positive integer >1!']);
end
disp(' ')
disp(['Log-likelihood before learning: ', num2str(ll)]);
disp(' ')

[bnet2, LL2] = learn_params_em(engine, cases, max_em_iter);
disp(' ')
fprintf('HME: loglik before learning %f, after %d iters %f\n', ll, length(LL2),  LL2(end));
disp(' ')
disp('(Press any key to continue)');
pause
%-----------------------------------------------------------------------------------
% Classification problem: plot data & decision boundaries if the input data size = 2
% Regression problem: plot data & prediction if the input data size = 1
%-----------------------------------------------------------------------------------
if (type==2)&(nodes_info(2,1)==2)&(~isempty(test_path)),
    fh1=hme_class_plot(bnet2, nodes_info, train_data, test_data);
    disp(' ');
    disp('(See the figure)');
elseif (type==2)&(nodes_info(2,1)==2)&(isempty(test_path)),
    fh1=hme_class_plot(bnet2, nodes_info, train_data);
    disp(' ');
    disp('(See the figure)');
elseif (type==1)&(nodes_info(2,1)==1)&(~isempty(test_path)),
    fh1=hme_reg_plot(bnet2, nodes_info, train_data, test_data);
    disp(' ');
    disp('(See the figure)');
elseif (type==1)&(nodes_info(2,1)==1)&(isempty(test_path)),
    fh1=hme_reg_plot(bnet2, nodes_info, train_data);
    disp(' ')
    disp('(See the figure)');
end
%-----------------------------------------------------------------------------------
% Classification problem: plot confusion matrix
%-----------------------------------------------------------------------------------
if (type==2)
    ztrain=fhme(bnet2, nodes_info, train_d, size(train_d,1));
    [Htrain, trainRate]=confmat(ztrain, train_t); % CM on the training set
    fh2=figure('Name','Confusion matrix', 'MenuBar', 'none', 'NumberTitle', 'off');
    if (~isempty(test_path))&(size(test_data,2)>cov_dim),
        ztest=fhme(bnet2, nodes_info, test_d, size(test_d,1));
        [Htest, testRate]=confmat(ztest, test_t);   % CM on the test set
        subplot(1,2,1);
    end
    plotmat(Htrain,'b','k',12)
    tick=[0.5:1:(0.5+nodes_info(2,end)-1)];
    set(gca,'XTick',tick)
    set(gca,'YTick',tick)
    grid('off')
    ylabel('True')
    xlabel('Prediction')
    title(['Confusion Matrix: training set (' num2str(trainRate(1)) '%)'])
    if (~isempty(test_path))&(size(test_data,2)>cov_dim),
        subplot(1,2,2)
        plotmat(Htest,'b','k',12)
        set(gca,'XTick',tick)
        set(gca,'YTick',tick)
        grid('off')
        ylabel('True')
        xlabel('Prediction')
        title(['Confusion Matrix: test set (' num2str(testRate(1)) '%)'])
    end
    disp(' ')
    disp('(Press any key to continue)');
    pause
end
%-----------------------------------------------------------------------------------
% Regression & Classification problem: calculate the predictions & plot the LL trace
%-----------------------------------------------------------------------------------
train_result=fhme(bnet2,nodes_info,train_d,size(train_d,1));
if ~isempty(test_path),
    test_result=fhme(bnet2,nodes_info,test_d,size(test_d,1));
end
fh3=figure('Name','Log-likelihood trace', 'MenuBar', 'none', 'NumberTitle', 'off')
plot(LL2,'-ro',...
                'MarkerEdgeColor','k',...
                'MarkerFaceColor',[1 1 0],...
                'MarkerSize',4)
title('Log-likelihood trace')
%-----------------------------------------------------------------------------------
% Regression & Classification problem: save the predictions
%-----------------------------------------------------------------------------------
clc
disp('------------------------------------------------------------------');
disp('                           Save the results                       ');
disp('------------------------------------------------------------------');
disp(' ')
%-----------------------------------------------------------------------------------
save_quest_m=input('Do you want to save the HME model (Y/N)? [Y default]: ', 's');
if isempty(save_quest_m),
    save_quest_m='Y';
end
if ~findstr(save_quest_m, ['Y', 'N']), error('Invalid input'); end
if save_quest_m=='Y',
    disp(' ');
    m_save=input('Insert the complete path for save the HME model (.mat):\n >> ', 's');
    if isempty(m_save), error('You must specify a path!'); end
    save(m_save, 'bnet2');
end
%-----------------------------------------------------------------------------------
disp(' ')
save_quest=input('Do you want to save the HME predictions (Y/N)? [Y default]: ', 's');
disp(' ')
if isempty(save_quest),
    save_quest='Y';
end
if ~findstr(save_quest, ['Y', 'N']), error('Invalid input'); end
if save_quest=='Y',
    tr_save=input('Insert the complete path for save the training data prediction (.mat):\n >> ', 's');
    if isempty(tr_save), error('You must specify a path!'); end
    save(tr_save, 'train_result');
    if ~isempty(test_path),
        disp(' ')
        te_save=input('Insert the complete path for save the test data prediction (.mat):\n >> ', 's');
        if isempty(te_save), error('You must specify a path!'); end
        save(te_save, 'test_result');
    end
end
clc
disp('----------------------------------------------------');
disp('                      B  Y  E !                     ');
disp('----------------------------------------------------');
pause(2)
%clear
clc


function [axisLabelCell,orientationStr,iop] = returnViewerAxisLabels(planC,scanNum)

indexS = planC{end};

if ~exist('scanNum','var') || isempty(scanNum)
    scanNum = 1;
end

try
    iop = planC{indexS.scan}(scanNum).scanInfo(1).imageOrientationPatient;

    if isempty(iop)
        iop = [1,0,0,0,1,0]'; % temporary. assign this during loading planC
    end

    [~,idx2] = max(abs(iop(1:3)));
    [~,idx1] = max(abs(iop(4:end)));

    iopProj = zeros(size(iop));
    iopProj(idx1 + 3) = iop(idx1 + 3);
    iopProj(idx2) = iop(idx2);

    iopProjSign = iopProj ./ abs(iop);

    iopProjSign(isnan(iopProjSign)) = 0;

    if isequal(abs(iopProjSign),[1; 0; 0; 0; 1; 0])
        sliceType = 'axial';
    elseif isequal(abs(iopProjSign),[1; 0; 0; 0; 0; 1])
        sliceType = 'coronal';
    else
        sliceType = 'sagittal';
    end

    switch sliceType

        case 'axial'
            % definitions
            HFS = [1; 0; 0; 0; 1; 0];
            HFP = [-1; 0; 0; 0; -1; 0];
            FFS = [-1; 0; 0; 0; 1; 0];
            FFP = [1; 0; 0; 0; -1; 0];

            if isequal(iopProjSign(:), HFS)
                axisLabelCell = {'A','P';'R','L';'S','I'};
                orientationStr = 'HFS';
            elseif isequal(iopProjSign(:), HFP)
                axisLabelCell = {'P','A';'L','R';'S','I'};
                orientationStr = 'HFP';
            elseif isequal(iopProjSign(:), FFS)
                axisLabelCell = {'A','P';'L','R';'S','I'};
                orientationStr = 'FFS';
            else %FFP
                axisLabelCell = {'P','A';'R','L';'S','I'};
                orientationStr = 'FFP';
            end
        case 'coronal'
            HFS = [1; 0; 0; 0; 0; 1];
            HFP = [-1; 0; 0; 0; 0; 1];
            FFS = [-1; 0; 0; 0; 0; -1];
            FFP = [1; 0; 0; 0; 0; -1];

            if isequal(iopProjSign(:), HFS)
                axisLabelCell = {'S','I';'R','L';'A','P'};
                orientationStr = 'HFS';
            elseif isequal(iopProjSign(:), HFP)
                axisLabelCell = {'S','I';'R','L';'A','P'};
                orientationStr = 'HFP';
            elseif isequal(iopProjSign(:), FFS)
                axisLabelCell = {'S','I';'R','L';'A','P'};
                orientationStr = 'FFS';
            else %FFP
                axisLabelCell = {'S','I';'R','L';'A','P'};
                orientationStr = 'FFP';
            end

        case 'sagittal' % eg [0; 1; 0; 0; 0; -1]
            HFS = [0; 1; 0; 0; 0; 1];
            HFP = [0; -1; 0; 0; 0; 1];
            FFS = [0; -1; 0; 0; 0; -1];
            FFP = [0; 1; 0; 0; 0; -1];

            if isequal(iopProjSign(:), HFS)
                axisLabelCell = {'A','P';'S','I';'R','L'};
                orientationStr = 'HFS';
            elseif isequal(iopProjSign(:), HFP)
                axisLabelCell = {'A','P';'I','S';'R','L'};
                orientationStr = 'HFP';
            elseif isequal(iopProjSign(:), FFS)
                axisLabelCell = {'P','A';'S','I';'R','L'};
                orientationStr = 'FFS';
            else %FFP
                axisLabelCell = {'P','A';'I','S';'R','L'};
                orientationStr = 'FFP';
            end
    end
catch err
    %default HFS
    disp(err);
    disp('Defaulting to HFS orientation');
    axisLabelCell = {'A','P';'R','L';'S','I'};
    orientationStr = 'HFS';
end


function disp(F)
%DISP   Display a SPHEREFUNV.
%
% See also SPHEREFUNV/DISPLAY.

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

loose = strcmp(get(0,'FormatSpacing'),'loose');

% Compact version:
if ( isempty(F) )
    fprintf('empty spherefunv\n\n')
    return
end

if ( F.isTransposed )
    tString = 'Row vector';
else
    tString = 'Column vector';
end

disp(['   spherefunv object ' '(' tString ') containing' ])
if ( loose )
    fprintf('\n');
end

% Display its two SPHERFUN halves.
for j = 1:3
    disp( F.components{j} );
end

end


function [rstat]=AddObsErr_v000(finname, nrow, foutname, act_row, errdef, rstat)

%randomize
if (rstat(1)~=0)
    randn('state',rstat)
else
    rstat=randn('state');
end

finp=fopen(finname,'rb');
inp=fread(finp,[nrow,inf],'double');
fclose(finp);

for in=1:size(act_row,1)
    fout=fopen(foutname(1,:),'wb');
    act_in=act_row(in,:);
    nd=size(act_in,2);
    if (~isempty(errdef))
        sR=errdef(in).sR;
        for (in1=1:size(inp,2))
            out=inp(act_in,in1)+sR*randn(nd,1);
            fwrite(fout,[inp(1,in1);out],'double');
        end
    else
        out=inp([1 act_in],:);
        fwrite(fout,out,'double');
    end
    fclose(fout);
end


function y = cumsum( x, dim )

%Disciplined convex/geometric programming information for SUM:
%   CUMSUM(X) and CUMSUM(X,DIM) are vectorized forms of addition. So
%   when CUMSUM is used in a DCP or DGP, elements in each subvector
%   must satisfy the corresponding combination rules for addition (see
%   PLUS). For example, suppose that X looks like this:
%      X = [ convex concave affine  ;
%            affine concave concave ]
%   Then CUMSUM(X,1) would be permittted, but CUMSUM(X,2) would not,
%   because the top row contains the sum of convex and concave terms, in
%   violation of the DCP ruleset. For DGPs, addition rules dictate that
%   the elements of X must be log-convex or log-affine.

s = x.size_;
switch nargin,
    case 0,
        error( 'Not enough input arguments.' );
    case 1,
        dim = cvx_default_dimension( s );
    case 2,
        if ~cvx_check_dimension( dim, false ),
            error( 'Second argument must be a dimension.' );
        end
end

if dim > length( s ) || s( dim ) <= 1,

    y = x;

else

    b = x.basis_;
    sb = size( b );
    need_perm = any( s( 1 : dim - 1 ) > 1 );
    if need_perm,
        ndxs = reshape( 1 : prod( s ), s );
        ndxs = permute( ndxs, [ dim, 1 : dim - 1, dim + 1 : length( s ) ] );
        b = b( :, ndxs );
    end
    b = reshape( b, prod( sb ) / s( dim ), s( dim ) );
    b = cumsum( b, 2 );
    b = reshape( b, sb );
    if need_perm,
        b( :, ndxs ) = b;
    end
    y = cvx( s, b );
    v = cvx_vexity( y );
    if any( isnan( v( : ) ) ),
        error( 'Disciplined convex programming error:\n   Illegal addition encountered (e.g., {convex} + {concave}).', 1 ); %#ok
    end

end

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


% PRELP  Loads and preprocesses LP from an MPS file.
%
% > [A,b,c,lenx,lbounds] = PRELP('problemname')
%    The above command results in an LP in standard form,
%    - Instead of specifying the problemname, you can also use PRELP([]), to
%    get the problem from the file /tmp/default.mat.
%    - Also, you may type PRELP without any input arguments, and get prompted
%    for a name.
%
% MINIMIZE  c'*x SUCH THAT  A*x = b AND  x>= 0.
%
%   So, you can solve it with SeDuMi:
% > [x,y,info] = SEDUMI(A,b,c);
%
% After solving, post-process it with
% > [x,objp] = POSTPROCESS(x(1:lenx),lbounds).
%
% REMARK  x(lenx+1:length(x)) will contain upper-bound slacks.
%
% IMPORTANT works only if LIPSOL is installed on your system.
%
% See also sedumi, getproblem, postprocess (LIPSOL), frompack, lipsol.

function [A,b,c,lenx,lbounds,times] = prelp(pname)
%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA%

global OUTFID
global Ubounds_exist
if ~exist('loadata','file') || ~exist('preprocess','file')
    error('To use PRELP, you need to have LIPSOL installed.')
end

%--------------------------------------------------
% LOAD LP PROBLEM INTO MEMORY
%--------------------------------------------------
if (nargin == 0)
    pname = input('Enter problem name: ','s');
end
t0 = cputime;
[A,b,c,lbounds,ubounds,BIG,NAME] = loadata(pname);
times(1) = cputime - t0;

%--------------------------------------------------
% PREPROCESS LP PROBLEM
% NB: Y.Zhang's preprocess returns lbounds for post-
% processing; the pre-processed problem has x>=0.
%--------------------------------------------------
t0 = cputime;
[A,b,c,lbounds,ubounds,FEASIBLE] = ...
    preprocess(A,b,c,lbounds,ubounds,BIG);
if ~FEASIBLE
    fprintf('\n');
    if isempty(OUTFID)
        return;
    end;
    msginf =  'Infeasibility detected in preprocessing';
    fprintf(OUTFID, [pname '  0   ' msginf '\n']);
    return;
end;
%[A,b,c,ubounds] = scaling(A,b,c,ubounds);
%--------------------------------------------------
% INSERT UBOUND- CONSTRAINTS IN THE A-MATRIX
%--------------------------------------------------
b = full(b); c = full(c);
[m,lenx] = size(A);
if Ubounds_exist
    nub = nnz(ubounds);
    A= [ A sparse(m,nub); sparse(1:nub,find(ubounds),1,nub,lenx) speye(nub) ];
    b = [b; nonzeros(ubounds)];
    c = [c; zeros(nub,1)];
else
    ubounds = [];
end
%--------------------------------------------------
% LOCATE DENSE COLUMNS
%--------------------------------------------------
%checkdense(A);
times(2) = cputime - t0;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%                                                                  %%%%%
%%%%    IEEE PES Power Grid Library - Optimal Power Flow - v21.07     %%%%%
%%%%          (https://github.com/power-grid-lib/pglib-opf)           %%%%%
%%%%             Benchmark Group - Active Power Increase              %%%%%
%%%%                         29 - July - 2021                         %%%%%
%%%%                                                                  %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function mpc = pglib_opf_case24_ieee_rts__api
mpc.version = '2';
mpc.baseMVA = 100.0;

%% area data
%	area	refbus
mpc.areas = [
	1	 1;
	2	 3;
	3	 8;
	4	 6;
];

%% bus data
%	bus_i	type	Pd	Qd	Gs	Bs	area	Vm	Va	baseKV	zone	Vmax	Vmin
mpc.bus = [
	1	 2	 207.30	 22.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	2	 2	 186.19	 20.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	3	 1	 345.50	 37.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	4	 1	 142.04	 15.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	5	 1	 136.28	 14.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	6	 1	 261.04	 28.00	 0.0	 -100.0	 2	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	7	 2	 239.93	 25.00	 0.0	 0.0	 2	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	8	 1	 328.23	 35.00	 0.0	 0.0	 2	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	9	 1	 335.90	 36.00	 0.0	 0.0	 1	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	10	 1	 374.29	 40.00	 0.0	 0.0	 2	    1.00000	    0.00000	 138.0	 1	    1.05000	    0.95000;
	11	 1	 0.0	 0.0	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	12	 1	 0.0	 0.0	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	13	 3	 508.65	 54.00	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	14	 2	 372.37	 39.00	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	15	 2	 608.47	 64.00	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	16	 2	 191.94	 20.00	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	17	 1	 0.0	 0.0	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	18	 2	 639.18	 68.00	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	19	 1	 347.42	 37.00	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	20	 1	 245.69	 26.00	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	21	 2	 0.0	 0.0	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	22	 2	 0.0	 0.0	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	23	 2	 0.0	 0.0	 0.0	 0.0	 3	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
	24	 1	 0.0	 0.0	 0.0	 0.0	 4	    1.00000	    0.00000	 230.0	 1	    1.05000	    0.95000;
];

%% generator data
%	bus	Pg	Qg	Qmax	Qmin	Vg	mBase	status	Pmax	Pmin
mpc.gen = [
	1	 43.5	 0.0	 40.0	 -40.0	 1.0	 100.0	 1	 79	 8.0; % PEL
	1	 109.5	 0.0	 106.0	 -106.0	 1.0	 100.0	 1	 211	 8.0; % PEL
	1	 41.3	 0.0	 38.0	 -38.0	 1.0	 100.0	 1	 75	 7.6; % PEL
	1	 42.8	 0.0	 39.0	 -39.0	 1.0	 100.0	 1	 78	 7.6; % NG
	2	 98.0	 0.0	 94.0	 -94.0	 1.0	 100.0	 1	 188	 8.0; % NG
	2	 95.0	 0.0	 91.0	 -91.0	 1.0	 100.0	 1	 182	 8.0; % PEL
	2	 91.8	 0.0	 88.0	 -88.0	 1.0	 100.0	 1	 176	 7.6; % NG
	2	 335.3	 0.0	 332.0	 -332.0	 1.0	 100.0	 1	 663	 7.6; % COW
	7	 221.25	 0.0	 215.0	 -215.0	 1.0	 100.0	 1	 430	 12.5; % NG
	7	 82.75	 0.0	 77.0	 -77.0	 1.0	 100.0	 1	 153	 12.5; % NG
	7	 303.75	 0.0	 298.0	 -298.0	 1.0	 100.0	 1	 595	 12.5; % COW
	13	 289.25	 0.0	 272.0	 -272.0	 1.0	 100.0	 1	 544	 34.5; % NG
	13	 288.25	 0.0	 271.0	 -271.0	 1.0	 100.0	 1	 542	 34.5; % NG
	13	 321.75	 0.0	 305.0	 -305.0	 1.0	 100.0	 1	 609	 34.5; % COW
	14	 0.0	 0.0	 252.0	 -252.0	 1.0	 100.0	 1	 0	 0.0; % SYNC
	15	 80.1	 0.0	 94.8	 -94.8	 1.0	 100.0	 1	 159	 1.2; % NG
	15	 103.6	 0.0	 103.0	 -103.0	 1.0	 100.0	 1	 206	 1.2; % COW
	15	 98.1	 0.0	 98.0	 -98.0	 1.0	 100.0	 1	 195	 1.2; % NG
	15	 81.6	 0.0	 94.8	 -94.8	 1.0	 100.0	 1	 162	 1.2; % NG
	15	 70.1	 0.0	 94.8	 -94.8	 1.0	 100.0	 1	 139	 1.2; % NG
	15	 116.575	 0.0	 103.0	 -103.0	 1.0	 100.0	 1	 206	 27.15; % NG
	16	 308.075	 0.0	 295.0	 -295.0	 1.0	 100.0	 1	 589	 27.15; % NG
	18	 216.0	 4.5	 200.0	 -191.0	 1.0	 100.0	 1	 382	 50.0; % NG
	21	 362.5	 0.0	 338.0	 -338.0	 1.0	 100.0	 1	 675	 50.0; % COW
	22	 113.5	 0.0	 111.0	 -111.0	 1.0	 100.0	 1	 222	 5.0; % NG
	22	 94.5	 0.0	 92.0	 -92.0	 1.0	 100.0	 1	 184	 5.0; % NG
	22	 75.5	 0.0	 73.0	 -73.0	 1.0	 100.0	 1	 146	 5.0; % NG
	22	 119.0	 0.0	 117.0	 -117.0	 1.0	 100.0	 1	 233	 5.0; % COW
	22	 110.5	 0.0	 108.0	 -108.0	 1.0	 100.0	 1	 216	 5.0; % NG
	22	 44.0	 0.0	 42.0	 -42.0	 1.0	 100.0	 1	 83	 5.0; % NG
	23	 224.075	 0.0	 211.0	 -211.0	 1.0	 100.0	 1	 421	 27.15; % NG
	23	 159.575	 0.0	 146.0	 -146.0	 1.0	 100.0	 1	 292	 27.15; % COW
	23	 226.0	 0.0	 191.0	 -191.0	 1.0	 100.0	 1	 382	 70.0; % NG
];

%% generator cost data
%	2	startup	shutdown	n	c(n-1)	...	c0
mpc.gencost = [
	2	 1500.0	 0.0	 3	   0.000000	 130.000000	 400.684900; % PEL
	2	 1500.0	 0.0	 3	   0.000000	 130.000000	 400.684900; % PEL
	2	 1500.0	 0.0	 3	   0.014142	  16.081100	 212.307600; % PEL
	2	 1500.0	 0.0	 3	   0.014142	  16.081100	 212.307600; % NG
	2	 1500.0	 0.0	 3	   0.000000	 130.000000	 400.684900; % NG
	2	 1500.0	 0.0	 3	   0.000000	 130.000000	 400.684900; % PEL
	2	 1500.0	 0.0	 3	   0.014142	  16.081100	 212.307600; % NG
	2	 1500.0	 0.0	 3	   0.014142	  16.081100	 212.307600; % COW
	2	 1500.0	 0.0	 3	   0.052672	  43.661500	 781.521000; % NG
	2	 1500.0	 0.0	 3	   0.052672	  43.661500	 781.521000; % NG
	2	 1500.0	 0.0	 3	   0.052672	  43.661500	 781.521000; % COW
	2	 1500.0	 0.0	 3	   0.007170	  48.580400	 832.757500; % NG
	2	 1500.0	 0.0	 3	   0.007170	  48.580400	 832.757500; % NG
	2	 1500.0	 0.0	 3	   0.007170	  48.580400	 832.757500; % COW
	2	 1500.0	 0.0	 3	   0.000000	   0.000000	   0.000000; % SYNC
	2	 1500.0	 0.0	 3	   0.328412	  56.564000	  86.385200; % NG
	2	 1500.0	 0.0	 3	   0.328412	  56.564000	  86.385200; % COW
	2	 1500.0	 0.0	 3	   0.328412	  56.564000	  86.385200; % NG
	2	 1500.0	 0.0	 3	   0.328412	  56.564000	  86.385200; % NG
	2	 1500.0	 0.0	 3	   0.328412	  56.564000	  86.385200; % NG
	2	 1500.0	 0.0	 3	   0.008342	  12.388300	 382.239100; % NG
	2	 1500.0	 0.0	 3	   0.008342	  12.388300	 382.239100; % NG
	2	 1500.0	 0.0	 3	   0.000213	   4.423100	 395.374900; % NG
	2	 1500.0	 0.0	 3	   0.000213	   4.423100	 395.374900; % COW
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % NG
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % NG
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % NG
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % COW
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % NG
	2	 1500.0	 0.0	 3	   0.000000	   0.001000	   0.001000; % NG
	2	 1500.0	 0.0	 3	   0.008342	  12.388300	 382.239100; % NG
	2	 1500.0	 0.0	 3	   0.008342	  12.388300	 382.239100; % COW
	2	 1500.0	 0.0	 3	   0.004895	  11.849500	 665.109400; % NG
];

%% branch data
%	fbus	tbus	r	x	b	rateA	rateB	rateC	ratio	angle	status	angmin	angmax
mpc.branch = [
	1	 2	 0.0026	 0.0139	 0.4611	 175.0	 193.0	 200.0	 0.0	 0.0	 1	 -30.0	 30.0;
	1	 3	 0.0546	 0.2112	 0.0572	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	1	 5	 0.0218	 0.0845	 0.0229	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	2	 4	 0.0328	 0.1267	 0.0343	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	2	 6	 0.0497	 0.192	 0.052	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	3	 9	 0.0308	 0.119	 0.0322	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	3	 24	 0.0023	 0.0839	 0.0	 400.0	 510.0	 600.0	 1.03	 0.0	 1	 -30.0	 30.0;
	4	 9	 0.0268	 0.1037	 0.0281	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	5	 10	 0.0228	 0.0883	 0.0239	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	6	 10	 0.0139	 0.0605	 2.459	 175.0	 193.0	 200.0	 0.0	 0.0	 1	 -30.0	 30.0;
	7	 8	 0.0159	 0.0614	 0.0166	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	8	 9	 0.0427	 0.1651	 0.0447	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	8	 10	 0.0427	 0.1651	 0.0447	 175.0	 208.0	 220.0	 0.0	 0.0	 1	 -30.0	 30.0;
	9	 11	 0.0023	 0.0839	 0.0	 400.0	 510.0	 600.0	 1.03	 0.0	 1	 -30.0	 30.0;
	9	 12	 0.0023	 0.0839	 0.0	 400.0	 510.0	 600.0	 1.03	 0.0	 1	 -30.0	 30.0;
	10	 11	 0.0023	 0.0839	 0.0	 400.0	 510.0	 600.0	 1.02	 0.0	 1	 -30.0	 30.0;
	10	 12	 0.0023	 0.0839	 0.0	 400.0	 510.0	 600.0	 1.02	 0.0	 1	 -30.0	 30.0;
	11	 13	 0.0061	 0.0476	 0.0999	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	11	 14	 0.0054	 0.0418	 0.0879	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	12	 13	 0.0061	 0.0476	 0.0999	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	12	 23	 0.0124	 0.0966	 0.203	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	13	 23	 0.0111	 0.0865	 0.1818	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	14	 16	 0.005	 0.0389	 0.0818	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	15	 16	 0.0022	 0.0173	 0.0364	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	15	 21	 0.0063	 0.049	 0.103	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	15	 21	 0.0063	 0.049	 0.103	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	15	 24	 0.0067	 0.0519	 0.1091	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	16	 17	 0.0033	 0.0259	 0.0545	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	16	 19	 0.003	 0.0231	 0.0485	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	17	 18	 0.0018	 0.0144	 0.0303	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	17	 22	 0.0135	 0.1053	 0.2212	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	18	 21	 0.0033	 0.0259	 0.0545	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	18	 21	 0.0033	 0.0259	 0.0545	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	19	 20	 0.0051	 0.0396	 0.0833	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	19	 20	 0.0051	 0.0396	 0.0833	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	20	 23	 0.0028	 0.0216	 0.0455	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	20	 23	 0.0028	 0.0216	 0.0455	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
	21	 22	 0.0087	 0.0678	 0.1424	 500.0	 600.0	 625.0	 0.0	 0.0	 1	 -30.0	 30.0;
];

% INFO    : === Translation Options ===
% INFO    : Load Model:                  from file ./pglib_opf_case24_ieee_rts.m.api.sol
% INFO    : Gen Active Capacity Model:   stat
% INFO    : Gen Reactive Capacity Model: al50ag
% INFO    : Gen Active Cost Model:       stat
% INFO    :
% INFO    : === Load Replacement Notes ===
% INFO    : Bus 1	: Pd=108.0, Qd=22.0 -> Pd=207.30, Qd=22.00
% INFO    : Bus 2	: Pd=97.0, Qd=20.0 -> Pd=186.19, Qd=20.00
% INFO    : Bus 3	: Pd=180.0, Qd=37.0 -> Pd=345.50, Qd=37.00
% INFO    : Bus 4	: Pd=74.0, Qd=15.0 -> Pd=142.04, Qd=15.00
% INFO    : Bus 5	: Pd=71.0, Qd=14.0 -> Pd=136.28, Qd=14.00
% INFO    : Bus 6	: Pd=136.0, Qd=28.0 -> Pd=261.04, Qd=28.00
% INFO    : Bus 7	: Pd=125.0, Qd=25.0 -> Pd=239.93, Qd=25.00
% INFO    : Bus 8	: Pd=171.0, Qd=35.0 -> Pd=328.23, Qd=35.00
% INFO    : Bus 9	: Pd=175.0, Qd=36.0 -> Pd=335.90, Qd=36.00
% INFO    : Bus 10	: Pd=195.0, Qd=40.0 -> Pd=374.29, Qd=40.00
% INFO    : Bus 13	: Pd=265.0, Qd=54.0 -> Pd=508.65, Qd=54.00
% INFO    : Bus 14	: Pd=194.0, Qd=39.0 -> Pd=372.37, Qd=39.00
% INFO    : Bus 15	: Pd=317.0, Qd=64.0 -> Pd=608.47, Qd=64.00
% INFO    : Bus 16	: Pd=100.0, Qd=20.0 -> Pd=191.94, Qd=20.00
% INFO    : Bus 18	: Pd=333.0, Qd=68.0 -> Pd=639.18, Qd=68.00
% INFO    : Bus 19	: Pd=181.0, Qd=37.0 -> Pd=347.42, Qd=37.00
% INFO    : Bus 20	: Pd=128.0, Qd=26.0 -> Pd=245.69, Qd=26.00
% INFO    :
% INFO    : === Generator Setpoint Replacement Notes ===
% INFO    : Gen at bus 1	: Pg=18.0, Qg=5.0 -> Pg=73.0, Qg=1.0
% INFO    : Gen at bus 1	: Pg=18.0, Qg=5.0 -> Pg=73.0, Qg=1.0
% INFO    : Gen at bus 1	: Pg=45.6, Qg=2.5 -> Pg=72.0, Qg=1.0
% INFO    : Gen at bus 1	: Pg=45.6, Qg=2.5 -> Pg=72.0, Qg=1.0
% INFO    : Gen at bus 2	: Pg=18.0, Qg=5.0 -> Pg=157.0, Qg=31.0
% INFO    : Gen at bus 2	: Pg=18.0, Qg=5.0 -> Pg=157.0, Qg=31.0
% INFO    : Gen at bus 2	: Pg=45.6, Qg=2.5 -> Pg=156.0, Qg=31.0
% INFO    : Gen at bus 2	: Pg=45.6, Qg=2.5 -> Pg=156.0, Qg=31.0
% INFO    : Gen at bus 7	: Pg=62.5, Qg=30.0 -> Pg=126.0, Qg=42.0
% INFO    : Gen at bus 7	: Pg=62.5, Qg=30.0 -> Pg=126.0, Qg=42.0
% INFO    : Gen at bus 7	: Pg=62.5, Qg=30.0 -> Pg=126.0, Qg=42.0
% INFO    : Gen at bus 13	: Pg=133.0, Qg=40.0 -> Pg=410.0, Qg=105.0
% INFO    : Gen at bus 13	: Pg=133.0, Qg=40.0 -> Pg=410.0, Qg=105.0
% INFO    : Gen at bus 13	: Pg=133.0, Qg=40.0 -> Pg=410.0, Qg=105.0
% INFO    : Gen at bus 14	: Pg=0.0, Qg=75.0 -> Pg=0.0, Qg=210.0
% INFO    : Gen at bus 15	: Pg=7.2, Qg=3.0 -> Pg=132.0, Qg=79.0
% INFO    : Gen at bus 15	: Pg=7.2, Qg=3.0 -> Pg=132.0, Qg=79.0
% INFO    : Gen at bus 15	: Pg=7.2, Qg=3.0 -> Pg=132.0, Qg=79.0
% INFO    : Gen at bus 15	: Pg=7.2, Qg=3.0 -> Pg=132.0, Qg=79.0
% INFO    : Gen at bus 15	: Pg=7.2, Qg=3.0 -> Pg=132.0, Qg=79.0
% INFO    : Gen at bus 15	: Pg=104.65, Qg=15.0 -> Pg=184.0, Qg=79.0
% INFO    : Gen at bus 16	: Pg=104.65, Qg=15.0 -> Pg=522.0, Qg=-34.0
% INFO    : Gen at bus 18	: Pg=250.0, Qg=75.0 -> Pg=301.0, Qg=32.0
% INFO    : Gen at bus 21	: Pg=250.0, Qg=75.0 -> Pg=203.0, Qg=-118.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 22	: Pg=30.0, Qg=3.0 -> Pg=68.0, Qg=-9.0
% INFO    : Gen at bus 23	: Pg=104.65, Qg=15.0 -> Pg=237.0, Qg=15.0
% INFO    : Gen at bus 23	: Pg=104.65, Qg=15.0 -> Pg=237.0, Qg=15.0
% INFO    : Gen at bus 23	: Pg=245.0, Qg=62.5 -> Pg=323.0, Qg=15.0
% INFO    :
% INFO    : === Generator Reactive Capacity Atleast Setpoint Value Notes ===
% INFO    : Gen at bus 1	: Qg 1.0, Qmin 0.0, Qmax 10.0 -> Qmin -1.2, Qmax 10.0
% INFO    : Gen at bus 1	: Qg 1.0, Qmin 0.0, Qmax 10.0 -> Qmin -1.2, Qmax 10.0
% INFO    : Gen at bus 2	: Qg 31.0, Qmin 0.0, Qmax 10.0 -> Qmin -37.2, Qmax 37.2
% INFO    : Gen at bus 2	: Qg 31.0, Qmin 0.0, Qmax 10.0 -> Qmin -37.2, Qmax 37.2
% INFO    : Gen at bus 2	: Qg 31.0, Qmin -25.0, Qmax 30.0 -> Qmin -37.2, Qmax 37.2
% INFO    : Gen at bus 2	: Qg 31.0, Qmin -25.0, Qmax 30.0 -> Qmin -37.2, Qmax 37.2
% INFO    : Gen at bus 7	: Qg 42.0, Qmin 0.0, Qmax 60.0 -> Qmin -50.4, Qmax 60.0
% INFO    : Gen at bus 7	: Qg 42.0, Qmin 0.0, Qmax 60.0 -> Qmin -50.4, Qmax 60.0
% INFO    : Gen at bus 7	: Qg 42.0, Qmin 0.0, Qmax 60.0 -> Qmin -50.4, Qmax 60.0
% INFO    : Gen at bus 13	: Qg 105.0, Qmin 0.0, Qmax 80.0 -> Qmin -126.0, Qmax 126.0
% INFO    : Gen at bus 13	: Qg 105.0, Qmin 0.0, Qmax 80.0 -> Qmin -126.0, Qmax 126.0
% INFO    : Gen at bus 13	: Qg 105.0, Qmin 0.0, Qmax 80.0 -> Qmin -126.0, Qmax 126.0
% INFO    : Gen at bus 14	: Qg 210.0, Qmin -50.0, Qmax 200.0 -> Qmin -252.0, Qmax 252.0
% INFO    : Gen at bus 15	: Qg 79.0, Qmin 0.0, Qmax 6.0 -> Qmin -94.8, Qmax 94.8
% INFO    : Gen at bus 15	: Qg 79.0, Qmin 0.0, Qmax 6.0 -> Qmin -94.8, Qmax 94.8
% INFO    : Gen at bus 15	: Qg 79.0, Qmin 0.0, Qmax 6.0 -> Qmin -94.8, Qmax 94.8
% INFO    : Gen at bus 15	: Qg 79.0, Qmin 0.0, Qmax 6.0 -> Qmin -94.8, Qmax 94.8
% INFO    : Gen at bus 15	: Qg 79.0, Qmin 0.0, Qmax 6.0 -> Qmin -94.8, Qmax 94.8
% INFO    : Gen at bus 15	: Qg 79.0, Qmin -50.0, Qmax 80.0 -> Qmin -94.8, Qmax 80.0
% INFO    : Gen at bus 21	: Qg -118.0, Qmin -50.0, Qmax 200.0 -> Qmin -141.6, Qmax 200.0
% INFO    :
% INFO    : === Generator Classification Notes ===
% INFO    : PEL    4   -     6.70
% INFO    : SYNC   1   -     0.00
% INFO    : COW    7   -    23.79
% INFO    : NG     21  -    69.51
% INFO    :
% INFO    : === Generator Active Capacity Stat Model Notes ===
% INFO    : Gen at bus 1 - PEL	: Pg=73.0, Pmax=20.0 -> Pmax=79   samples: 7
% INFO    : Gen at bus 1 - PEL	: Pg=73.0, Pmax=20.0 -> Pmax=211   samples: 1
% INFO    : Gen at bus 1 - PEL	: Pg=72.0, Pmax=76.0 -> Pmax=75   samples: 9
% INFO    : Gen at bus 1 - NG	: Pg=72.0, Pmax=76.0 -> Pmax=78   samples: 2
% INFO    : Gen at bus 2 - NG	: Pg=157.0, Pmax=20.0 -> Pmax=188   samples: 1
% WARNING : Failed to find a generator capacity within (157.0-785.0) after 100 samples, using percent increase model
% INFO    : Gen at bus 2 - PEL	: Pg=157.0, Pmax=20.0 -> Pmax=182   samples: 100
% INFO    : Gen at bus 2 - NG	: Pg=156.0, Pmax=76.0 -> Pmax=176   samples: 1
% INFO    : Gen at bus 2 - COW	: Pg=156.0, Pmax=76.0 -> Pmax=663   samples: 3
% INFO    : Gen at bus 7 - NG	: Pg=126.0, Pmax=100.0 -> Pmax=430   samples: 2
% INFO    : Gen at bus 7 - NG	: Pg=126.0, Pmax=100.0 -> Pmax=153   samples: 1
% INFO    : Gen at bus 7 - COW	: Pg=126.0, Pmax=100.0 -> Pmax=595   samples: 1
% INFO    : Gen at bus 13 - NG	: Pg=410.0, Pmax=197.0 -> Pmax=544   samples: 18
% INFO    : Gen at bus 13 - NG	: Pg=410.0, Pmax=197.0 -> Pmax=542   samples: 17
% INFO    : Gen at bus 13 - COW	: Pg=410.0, Pmax=197.0 -> Pmax=609   samples: 2
% INFO    : Gen at bus 14 - SYNC	: Pg=0.0, Pmax=0.0 -> Pmax=0   samples: 0
% INFO    : Gen at bus 15 - NG	: Pg=132.0, Pmax=12.0 -> Pmax=159   samples: 4
% INFO    : Gen at bus 15 - COW	: Pg=132.0, Pmax=12.0 -> Pmax=206   samples: 2
% INFO    : Gen at bus 15 - NG	: Pg=132.0, Pmax=12.0 -> Pmax=195   samples: 3
% INFO    : Gen at bus 15 - NG	: Pg=132.0, Pmax=12.0 -> Pmax=162   samples: 10
% INFO    : Gen at bus 15 - NG	: Pg=132.0, Pmax=12.0 -> Pmax=139   samples: 1
% INFO    : Gen at bus 15 - NG	: Pg=184.0, Pmax=155.0 -> Pmax=206   samples: 1
% WARNING : Failed to find a generator capacity within (522.0-2610.0) after 100 samples, using percent increase model
% INFO    : Gen at bus 16 - NG	: Pg=522.0, Pmax=155.0 -> Pmax=589   samples: 100
% INFO    : Gen at bus 18 - NG	: Pg=301.0, Pmax=400.0 -> Pmax=382   samples: 10
% INFO    : Gen at bus 21 - COW	: Pg=203.0, Pmax=400.0 -> Pmax=675   samples: 2
% INFO    : Gen at bus 22 - NG	: Pg=68.0, Pmax=50.0 -> Pmax=222   samples: 2
% INFO    : Gen at bus 22 - NG	: Pg=68.0, Pmax=50.0 -> Pmax=184   samples: 1
% INFO    : Gen at bus 22 - NG	: Pg=68.0, Pmax=50.0 -> Pmax=146   samples: 2
% INFO    : Gen at bus 22 - COW	: Pg=68.0, Pmax=50.0 -> Pmax=233   samples: 1
% INFO    : Gen at bus 22 - NG	: Pg=68.0, Pmax=50.0 -> Pmax=216   samples: 1
% INFO    : Gen at bus 22 - NG	: Pg=68.0, Pmax=50.0 -> Pmax=83   samples: 1
% INFO    : Gen at bus 23 - NG	: Pg=237.0, Pmax=155.0 -> Pmax=421   samples: 2
% INFO    : Gen at bus 23 - COW	: Pg=237.0, Pmax=155.0 -> Pmax=292   samples: 3
% INFO    : Gen at bus 23 - NG	: Pg=323.0, Pmax=350.0 -> Pmax=382   samples: 35
% INFO    :
% INFO    : === Generator Active Capacity LB Model Notes ===
% INFO    : Gen at bus 1	: Pmin=16.0 -> Pmin=8.0
% INFO    : Gen at bus 1	: Pmin=16.0 -> Pmin=8.0
% INFO    : Gen at bus 1	: Pmin=15.2 -> Pmin=7.6
% INFO    : Gen at bus 1	: Pmin=15.2 -> Pmin=7.6
% INFO    : Gen at bus 2	: Pmin=16.0 -> Pmin=8.0
% INFO    : Gen at bus 2	: Pmin=16.0 -> Pmin=8.0
% INFO    : Gen at bus 2	: Pmin=15.2 -> Pmin=7.6
% INFO    : Gen at bus 2	: Pmin=15.2 -> Pmin=7.6
% INFO    : Gen at bus 7	: Pmin=25.0 -> Pmin=12.5
% INFO    : Gen at bus 7	: Pmin=25.0 -> Pmin=12.5
% INFO    : Gen at bus 7	: Pmin=25.0 -> Pmin=12.5
% INFO    : Gen at bus 13	: Pmin=69.0 -> Pmin=34.5
% INFO    : Gen at bus 13	: Pmin=69.0 -> Pmin=34.5
% INFO    : Gen at bus 13	: Pmin=69.0 -> Pmin=34.5
% INFO    : Gen at bus 15	: Pmin=2.4 -> Pmin=1.2
% INFO    : Gen at bus 15	: Pmin=2.4 -> Pmin=1.2
% INFO    : Gen at bus 15	: Pmin=2.4 -> Pmin=1.2
% INFO    : Gen at bus 15	: Pmin=2.4 -> Pmin=1.2
% INFO    : Gen at bus 15	: Pmin=2.4 -> Pmin=1.2
% INFO    : Gen at bus 15	: Pmin=54.3 -> Pmin=27.15
% INFO    : Gen at bus 16	: Pmin=54.3 -> Pmin=27.15
% INFO    : Gen at bus 18	: Pmin=100.0 -> Pmin=50.0
% INFO    : Gen at bus 21	: Pmin=100.0 -> Pmin=50.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 22	: Pmin=10.0 -> Pmin=5.0
% INFO    : Gen at bus 23	: Pmin=54.3 -> Pmin=27.15
% INFO    : Gen at bus 23	: Pmin=54.3 -> Pmin=27.15
% INFO    : Gen at bus 23	: Pmin=140.0 -> Pmin=70.0
% INFO    :
% INFO    : === Generator Reactive Capacity Atleast Max 50 Percent Active Model Notes ===
% INFO    : Gen at bus 1 - PEL	: Pmax 79.0, Qmin -1.2, Qmax 10.0 -> Qmin -40.0, Qmax 40.0
% INFO    : Gen at bus 1 - PEL	: Pmax 211.0, Qmin -1.2, Qmax 10.0 -> Qmin -106.0, Qmax 106.0
% INFO    : Gen at bus 1 - PEL	: Pmax 75.0, Qmin -25.0, Qmax 30.0 -> Qmin -38.0, Qmax 38.0
% INFO    : Gen at bus 1 - NG	: Pmax 78.0, Qmin -25.0, Qmax 30.0 -> Qmin -39.0, Qmax 39.0
% INFO    : Gen at bus 2 - NG	: Pmax 188.0, Qmin -37.2, Qmax 37.2 -> Qmin -94.0, Qmax 94.0
% INFO    : Gen at bus 2 - PEL	: Pmax 182.0, Qmin -37.2, Qmax 37.2 -> Qmin -91.0, Qmax 91.0
% INFO    : Gen at bus 2 - NG	: Pmax 176.0, Qmin -37.2, Qmax 37.2 -> Qmin -88.0, Qmax 88.0
% INFO    : Gen at bus 2 - COW	: Pmax 663.0, Qmin -37.2, Qmax 37.2 -> Qmin -332.0, Qmax 332.0
% INFO    : Gen at bus 7 - NG	: Pmax 430.0, Qmin -50.4, Qmax 60.0 -> Qmin -215.0, Qmax 215.0
% INFO    : Gen at bus 7 - NG	: Pmax 153.0, Qmin -50.4, Qmax 60.0 -> Qmin -77.0, Qmax 77.0
% INFO    : Gen at bus 7 - COW	: Pmax 595.0, Qmin -50.4, Qmax 60.0 -> Qmin -298.0, Qmax 298.0
% INFO    : Gen at bus 13 - NG	: Pmax 544.0, Qmin -126.0, Qmax 126.0 -> Qmin -272.0, Qmax 272.0
% INFO    : Gen at bus 13 - NG	: Pmax 542.0, Qmin -126.0, Qmax 126.0 -> Qmin -271.0, Qmax 271.0
% INFO    : Gen at bus 13 - COW	: Pmax 609.0, Qmin -126.0, Qmax 126.0 -> Qmin -305.0, Qmax 305.0
% INFO    : Gen at bus 15 - COW	: Pmax 206.0, Qmin -94.8, Qmax 94.8 -> Qmin -103.0, Qmax 103.0
% INFO    : Gen at bus 15 - NG	: Pmax 195.0, Qmin -94.8, Qmax 94.8 -> Qmin -98.0, Qmax 98.0
% INFO    : Gen at bus 15 - NG	: Pmax 206.0, Qmin -94.8, Qmax 80.0 -> Qmin -103.0, Qmax 103.0
% INFO    : Gen at bus 16 - NG	: Pmax 589.0, Qmin -50.0, Qmax 80.0 -> Qmin -295.0, Qmax 295.0
% INFO    : Gen at bus 18 - NG	: Pmax 382.0, Qmin -50.0, Qmax 200.0 -> Qmin -191.0, Qmax 200.0
% INFO    : Gen at bus 21 - COW	: Pmax 675.0, Qmin -141.6, Qmax 200.0 -> Qmin -338.0, Qmax 338.0
% INFO    : Gen at bus 22 - NG	: Pmax 222.0, Qmin -10.0, Qmax 16.0 -> Qmin -111.0, Qmax 111.0
% INFO    : Gen at bus 22 - NG	: Pmax 184.0, Qmin -10.0, Qmax 16.0 -> Qmin -92.0, Qmax 92.0
% INFO    : Gen at bus 22 - NG	: Pmax 146.0, Qmin -10.0, Qmax 16.0 -> Qmin -73.0, Qmax 73.0
% INFO    : Gen at bus 22 - COW	: Pmax 233.0, Qmin -10.0, Qmax 16.0 -> Qmin -117.0, Qmax 117.0
% INFO    : Gen at bus 22 - NG	: Pmax 216.0, Qmin -10.0, Qmax 16.0 -> Qmin -108.0, Qmax 108.0
% INFO    : Gen at bus 22 - NG	: Pmax 83.0, Qmin -10.0, Qmax 16.0 -> Qmin -42.0, Qmax 42.0
% INFO    : Gen at bus 23 - NG	: Pmax 421.0, Qmin -50.0, Qmax 80.0 -> Qmin -211.0, Qmax 211.0
% INFO    : Gen at bus 23 - COW	: Pmax 292.0, Qmin -50.0, Qmax 80.0 -> Qmin -146.0, Qmax 146.0
% INFO    : Gen at bus 23 - NG	: Pmax 382.0, Qmin -25.0, Qmax 150.0 -> Qmin -191.0, Qmax 191.0
% INFO    :
% INFO    : === Generator Setpoint Replacement Notes ===
% INFO    : Gen at bus 1	: Pg=73.0, Qg=1.0 -> Pg=43.5, Qg=0.0
% INFO    : Gen at bus 1	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 1	: Pg=73.0, Qg=1.0 -> Pg=109.5, Qg=0.0
% INFO    : Gen at bus 1	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 1	: Pg=72.0, Qg=1.0 -> Pg=41.3, Qg=0.0
% INFO    : Gen at bus 1	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 1	: Pg=72.0, Qg=1.0 -> Pg=42.8, Qg=0.0
% INFO    : Gen at bus 1	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 2	: Pg=157.0, Qg=31.0 -> Pg=98.0, Qg=0.0
% INFO    : Gen at bus 2	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 2	: Pg=157.0, Qg=31.0 -> Pg=95.0, Qg=0.0
% INFO    : Gen at bus 2	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 2	: Pg=156.0, Qg=31.0 -> Pg=91.8, Qg=0.0
% INFO    : Gen at bus 2	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 2	: Pg=156.0, Qg=31.0 -> Pg=335.3, Qg=0.0
% INFO    : Gen at bus 2	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 7	: Pg=126.0, Qg=42.0 -> Pg=221.25, Qg=0.0
% INFO    : Gen at bus 7	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 7	: Pg=126.0, Qg=42.0 -> Pg=82.75, Qg=0.0
% INFO    : Gen at bus 7	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 7	: Pg=126.0, Qg=42.0 -> Pg=303.75, Qg=0.0
% INFO    : Gen at bus 7	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 13	: Pg=410.0, Qg=105.0 -> Pg=289.25, Qg=0.0
% INFO    : Gen at bus 13	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 13	: Pg=410.0, Qg=105.0 -> Pg=288.25, Qg=0.0
% INFO    : Gen at bus 13	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 13	: Pg=410.0, Qg=105.0 -> Pg=321.75, Qg=0.0
% INFO    : Gen at bus 13	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 14	: Pg=0.0, Qg=210.0 -> Pg=0.0, Qg=0.0
% INFO    : Gen at bus 14	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=132.0, Qg=79.0 -> Pg=80.1, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=132.0, Qg=79.0 -> Pg=103.6, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=132.0, Qg=79.0 -> Pg=98.1, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=132.0, Qg=79.0 -> Pg=81.6, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=132.0, Qg=79.0 -> Pg=70.1, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 15	: Pg=184.0, Qg=79.0 -> Pg=116.575, Qg=0.0
% INFO    : Gen at bus 15	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 16	: Pg=522.0, Qg=-34.0 -> Pg=308.075, Qg=0.0
% INFO    : Gen at bus 16	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 18	: Pg=301.0, Qg=32.0 -> Pg=216.0, Qg=4.5
% INFO    : Gen at bus 18	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 21	: Pg=203.0, Qg=-118.0 -> Pg=362.5, Qg=0.0
% INFO    : Gen at bus 21	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=113.5, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=94.5, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=75.5, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=119.0, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=110.5, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 22	: Pg=68.0, Qg=-9.0 -> Pg=44.0, Qg=0.0
% INFO    : Gen at bus 22	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 23	: Pg=237.0, Qg=15.0 -> Pg=224.075, Qg=0.0
% INFO    : Gen at bus 23	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 23	: Pg=237.0, Qg=15.0 -> Pg=159.575, Qg=0.0
% INFO    : Gen at bus 23	: Vg=1.0 -> Vg=1.0
% INFO    : Gen at bus 23	: Pg=323.0, Qg=15.0 -> Pg=226.0, Qg=0.0
% INFO    : Gen at bus 23	: Vg=1.0 -> Vg=1.0
% INFO    :
% INFO    : === Writing Matpower Case File Notes ===


function [ result ] = CREST_tracking( opts, varargin, config, display)
%Test function
global objSize;

LocGt=config.gt;
num_channels=64;

% training options (SGD)
opts.train = struct([]) ;
[opts, varargin] = vl_argparse(opts, varargin) ;

output_sigma_factor = 0.1;

gpuDevice(1);
[net1,avgImg]=initVGG16Net();

nFrame=config.nFrames;
[Gt]=config.gt;

result = zeros(length(nFrame), 4); result(1,:) = Gt(1,:);

% I only have a Titan Black GPU on my side. Its memory is limited.
% For objects with large size, I have to perform the downsampling.
% You can remove the downsampling on your side. The results might be little different.
scale=1;
global resize;
objSize=Gt(1,3:4);
if objSize(1)*objSize(2)>resize*resize
    scale=resize/max(objSize);
    disp('resized');
end

im1=imread(config.imgList{1});
im=imresize(im1,scale);
cell_size=4;
if size(im,3)==1
    im = cat(3, im, im, im);
    im1 = cat(3, im1, im1, im1);
end

targetLoc=round(Gt(1,:)*scale);
target_sz=[targetLoc(4) targetLoc(3)];
im_sz=size(im);
window_sz = get_search_window(target_sz, im_sz);
l1_patch_num = ceil(window_sz/ cell_size);
l1_patch_num=l1_patch_num-mod(l1_patch_num,2)+1;
cos_window = hann(l1_patch_num(1)) * hann(l1_patch_num(2))';

sz_window=size(cos_window);
pos = [targetLoc(2), targetLoc(1)] + floor(target_sz/2);
patch = get_subwindow(im, pos, window_sz);
meanImg=zeros(size(patch));
meanImg(:,:,1)=avgImg(1);
meanImg(:,:,2)=avgImg(2);
meanImg(:,:,3)=avgImg(3);
patch1 = single(patch) - meanImg;
net1.eval({'input',gpuArray(patch1)});

index=[23];
feat=cell(length(index),1);
for i=1:length(index)
    feat1 = gather(net1.vars(index(i)).value);
    feat1 = imResample(feat1, sz_window(1:2));
    feat{i} = bsxfun(@times, feat1, cos_window);
end
feat=feat{1};

[hf,wf,cf]=size(feat);
matrix=reshape(feat,hf*wf,cf);
coeff = pca(matrix);
coeff=coeff(:,1:num_channels);

target_sz1=ceil(target_sz/cell_size);
output_sigma = target_sz1*output_sigma_factor;
label=gaussian_shaped_labels(output_sigma, l1_patch_num);

label1=imresize(label,[size(im1,1) size(im1,1)])*255;
patch1=imresize(patch,[size(im1,1) size(im1,1)]);
imd=[im1];
%-------------------Display First frame----------
if display
    figure(2);
    set(gcf,'Position',[200 300 480 320],'MenuBar','none','ToolBar','none');
    hd = imshow(imd,'initialmagnification','fit'); hold on;
    rectangle('Position', Gt(1,:), 'EdgeColor', [0 0 1], 'Linewidth', 1);
    set(gca,'position',[0 0 1 1]);
    text(10,10,'1','Color','y', 'HorizontalAlignment', 'left', 'FontWeight','bold', 'FontSize', 30);
    hold off;
    drawnow;
end

%-------------------first frame initialization-----------
trainOpts.numEpochs=4000;

feat_=reshape(feat,hf*wf,cf);
feat_=feat_*coeff;
featPCA=reshape(feat_,hf,wf,num_channels);

net_online=initNet(target_sz1);

trainOpts.batchSize = 1 ;
trainOpts.numSubBatches = 1 ;
trainOpts.continue = true ;
trainOpts.gpus = 1 ;
trainOpts.prefetch = true ;

trainOpts.expDir = opts.expDir ;
trainOpts.learningRate=5e-8;
trainOpts.weightDecay= 1;

train=1;
imdb=[];
input={featPCA label};
featPCA1st=featPCA;
opts.train.gpus=1;
bopts.useGpu = numel(opts.train.gpus) > 0 ;
info = cnn_train_dag(net_online, imdb, input,getBatchWrapper(bopts), ...
                     trainOpts, ...
                     'train', train, ...
                     opts.train) ;

net_online.move('gpu');

%----------------online prediction------------------
motion_sigma_factor=0.6;
cell_size=4;
global num_update;
num_update=2;
cur=1;
feat_update=cell(num_update,1);
label_update=cell(num_update,1);
target_szU=target_sz;
for i=2:nFrame
    im1=imread(config.imgList{i});
    im=imresize(im1,scale);
    if size(im1,3)==1
        im = cat(3, im, im, im);
        im1 = cat(3, im1, im1, im1);
    end

    patch = get_subwindow(im, pos, window_sz);
    patch1 = single(patch) - meanImg;
    net1.eval({'input',gpuArray(patch1)});

    feat=cell(length(index),1);
    for j=1:length(index)
        feat1 = gather(net1.vars(index(j)).value);
        feat1 = imResample(feat1, sz_window(1:2));
        feat{j} = bsxfun(@times, feat1, cos_window);
    end
    feat=feat{1};

    feat_=reshape(feat,hf*wf,cf);
    feat_=feat_*coeff;
    featPCA=reshape(feat_,hf,wf,num_channels);

    net_online.eval({'input1',gpuArray(featPCA),'input2',gpuArray(featPCA1st)});
    regression_map=gather(net_online.vars(10).value);

    motion_sigma = target_sz1*motion_sigma_factor;
    motion_map=gaussian_shaped_labels(motion_sigma, l1_patch_num);

    response=regression_map.*motion_map;

    [vert_delta, horiz_delta] = find(response == max(response(:)), 1);
    vert_delta  = vert_delta  - ceil(hf/2);
    horiz_delta = horiz_delta - ceil(wf/2);

    pos = pos + cell_size * [vert_delta, horiz_delta];

    target_szU=scale_estimation(im,pos,target_szU,window_sz,...
            net1,net_online,coeff,meanImg,featPCA1st);

    targetLoc=[pos([2,1]) - target_szU([2,1])/2, target_szU([2,1])];
    result(i,:)=round(targetLoc/scale);

    label1=imresize(regression_map,[size(im1,1) size(im1,1)])*255;
    patch1=imresize(patch,[size(im1,1) size(im1,1)]);
    imd=[im1];
%    -----------Display current frame-----------------
    if display
        hc = get(gca, 'Children'); delete(hc(1:end-1));
        set(hd,'cdata',imd); hold on;
        rectangle('Position', result(i,:), 'EdgeColor', [0 0 1], 'Linewidth', 1);
        set(gca,'position',[0 0 1 1]);
        text(10,10,num2str(i),'Color','y', 'HorizontalAlignment', 'left', 'FontWeight','bold', 'FontSize', 30);
        hold off;
        drawnow;
    end

     %-----------Model update-------------------------
     labelU=circshift(label,[vert_delta,horiz_delta]);
     feat_update{cur}=featPCA;
     label_update{cur}=labelU;

     if cur==num_update

        trainOpts.batchSize = 1 ;
        trainOpts.numSubBatches = 1 ;
        trainOpts.continue = true ;
        trainOpts.gpus = 1 ;
        trainOpts.prefetch = true ;

        trainOpts.expDir = 'exp/update/' ;
        trainOpts.learningRate = 2e-9;
        trainOpts.weightDecay= 1;
        trainOpts.numEpochs = 2;

        train=1;
        imdb=[];
        input={feat_update featPCA1st label_update};
        opts.train.gpus=1;
        bopts.useGpu = numel(opts.train.gpus) > 0 ;

        info = cnn_train_dag_update(net_online, imdb, input,getBatchWrapper(bopts), ...
                             trainOpts, ...
                             'train', train, ...
                             opts.train) ;
        net_online.move('gpu');

        cur=1;
    else
        cur=cur+1;
    end

end

end

function fn = getBatchWrapper(opts)
% -------------------------------------------------------------------------
fn = @(imdb,batch) getBatch(imdb,batch,false,opts,'prefetch',nargout==0) ;
end


% sub module for 1. order kinetics in simpltrans
c1 = exp(-lambda*dtdiff)*c1;


% EEGFILT -  (high|low|band)-pass filter data using two-way least-squares
%              FIR filtering. Optionally uses the window method instead of
%              least-squares. Multiple data channels and epochs supported.
%              Requires the MATLAB Signal Processing Toolbox.
% Usage:
%  >> [smoothdata] = eegfilt(data,srate,locutoff,hicutoff);
%  >> [smoothdata,filtwts] = eegfilt(data,srate,locutoff,hicutoff, ...
%                                    epochframes,filtorder,revfilt,firtype,causal);
% Inputs:
%   data        = (channels,frames*epochs) data to filter
%   srate       = data sampling rate (Hz)
%   locutoff    = low-edge frequency in pass band (Hz)  {0 -> lowpass}
%   hicutoff    = high-edge frequency in pass band (Hz) {0 -> highpass}
%   epochframes = frames per epoch (filter each epoch separately {def/0: data is 1 epoch}
%   filtorder   = length of the filter in points {default 3*fix(srate/locutoff)}
%   revfilt     = [0|1] reverse filter (i.e. bandpass filter to notch filter). {default 0}
%   firtype     = 'firls'|'fir1' {'firls'}
%   causal      = [0|1] use causal filter if set to 1 (default 0)
%
% Outputs:
%    smoothdata = smoothed data
%    filtwts    = filter coefficients [smoothdata <- filtfilt(filtwts,1,data)]
%
% See also: FIRLS, FILTFILT

% Author: Scott Makeig, Arnaud Delorme, Clemens Brunner SCCN/INC/UCSD, La Jolla, 1997

% Copyright (C) 4-22-97 from bandpass.m Scott Makeig, SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 05-08-97 fixed frequency bound computation -sm
% 10-22-97 added MINFREQ tests -sm
% 12-05-00 added ERROR calls -sm
% 01-25-02 reformated help & license, added links -ad
% 03-20-12 added firtype option -cb

function [smoothdata,filtwts] = eegfilt(data,srate,locutoff,hicutoff,epochframes,filtorder,revfilt,firtype,causal)

if nargin<4
    fprintf('');
    help eegfilt
    return
end

%if ~exist('firls')
%   error('*** EEGFILT requires the signal processing toolbox. ***');
%end

[chans frames] = size(data);
if chans > 1 && frames == 1,
    help eegfilt
    error('input data should be a row vector.');
end
nyq            = srate*0.5;  % Nyquist frequency
%MINFREQ = 0.1/nyq;
MINFREQ = 0;

minfac         = 3;    % this many (lo)cutoff-freq cycles in filter
min_filtorder  = 15;   % minimum filter length
trans          = 0.15; % fractional width of transition zones

if locutoff>0 && hicutoff > 0 && locutoff > hicutoff,
    error('locutoff > hicutoff ???\n');
end
if locutoff < 0 || hicutoff < 0,
    error('locutoff | hicutoff < 0 ???\n');
end

if locutoff>nyq,
    error('Low cutoff frequency cannot be > srate/2');
end

if hicutoff>nyq
    error('High cutoff frequency cannot be > srate/2');
end

if nargin<6
    filtorder = 0;
end
if nargin<7
    revfilt = 0;
end
if nargin<8
    firtype = 'firls';
end
if nargin<9
    causal = 0;
end

if strcmp(firtype, 'firls')
    warning('Using firls to estimate filter coefficients. We recommend that you use fir1 instead, which yields larger attenuation. In future, fir1 will be used by default!');
end

if isempty(filtorder) || filtorder==0,
    if locutoff>0,
        filtorder = minfac*fix(srate/locutoff);
    elseif hicutoff>0,
        filtorder = minfac*fix(srate/hicutoff);
    end

    if filtorder < min_filtorder
        filtorder = min_filtorder;
    end
end

if nargin<5
    epochframes = 0;
end
if epochframes ==0,
    epochframes = frames;    % default
end
epochs = fix(frames/epochframes);
if epochs*epochframes ~= frames,
    error('epochframes does not divide frames.\n');
end

if filtorder*3 > epochframes,   % Matlab filtfilt() restriction
    fprintf('eegfilt(): filter order is %d. ',filtorder);
    error('epochframes must be at least 3 times the filtorder.');
end
if (1+trans)*hicutoff/nyq > 1
    error('high cutoff frequency too close to Nyquist frequency');
end

if locutoff > 0 && hicutoff > 0,    % bandpass filter
    if revfilt
        fprintf('eegfilt() - performing %d-point notch filtering.\n',filtorder);
    else
        fprintf('eegfilt() - performing %d-point bandpass filtering.\n',filtorder);
    end
    fprintf('            If a message, ''Matrix is close to singular or badly scaled,'' appears,\n');
    fprintf('            then Matlab has failed to design a good filter. As a workaround, \n');
    fprintf('            for band-pass filtering, first highpass the data, then lowpass it.\n');
    if strcmp(firtype, 'firls')
        f=[MINFREQ (1-trans)*locutoff/nyq locutoff/nyq hicutoff/nyq (1+trans)*hicutoff/nyq 1];
        fprintf('eegfilt() - low transition band width is %1.1g Hz; high trans. band width, %1.1g Hz.\n',(f(3)-f(2))*srate/2, (f(5)-f(4))*srate/2);
        m=[0       0                      1            1            0                      0];
    elseif strcmp(firtype, 'fir1')
        filtwts = fir1(filtorder, [locutoff, hicutoff]./(srate/2));
    end
elseif locutoff > 0                % highpass filter
    if locutoff/nyq < MINFREQ
        error(sprintf('eegfilt() - highpass cutoff freq must be > %g Hz\n\n',MINFREQ*nyq));
    end
    fprintf('eegfilt() - performing %d-point highpass filtering.\n',filtorder);
    if strcmp(firtype, 'firls')
        f=[MINFREQ locutoff*(1-trans)/nyq locutoff/nyq 1];
        fprintf('eegfilt() - highpass transition band width is %1.1g Hz.\n',(f(3)-f(2))*srate/2);
        m=[   0             0                   1      1];
    elseif strcmp(firtype, 'fir1')
        filtwts = fir1(filtorder, locutoff./(srate/2), 'high');
    end
elseif hicutoff > 0                %  lowpass filter
    if hicutoff/nyq < MINFREQ
        error(sprintf('eegfilt() - lowpass cutoff freq must be > %g Hz',MINFREQ*nyq));
    end
    fprintf('eegfilt() - performing %d-point lowpass filtering.\n',filtorder);
    if strcmp(firtype, 'firls')
        f=[MINFREQ hicutoff/nyq hicutoff*(1+trans)/nyq 1];
        fprintf('eegfilt() - lowpass transition band width is %1.1g Hz.\n',(f(3)-f(2))*srate/2);
        m=[     1           1              0                 0];
    elseif strcmp(firtype, 'fir1')
        filtwts = fir1(filtorder, hicutoff./(srate/2));
    end
else
    error('You must provide a non-0 low or high cut-off frequency');
end
if revfilt
    if strcmp(firtype, 'fir1')
        error('Cannot reverse filter using ''fir1'' option');
    else
        m = double(~m);
    end
end

if strcmp(firtype, 'firls')
    filtwts = firls(filtorder,f,m); % get FIR filter coefficients
end

smoothdata = zeros(chans,frames);
for e = 1:epochs                % filter each epoch, channel
    for c=1:chans
        try
            if causal
                 smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filter(  filtwts,1,data(c,(e-1)*epochframes+1:e*epochframes));
            else smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(filtwts,1,data(c,(e-1)*epochframes+1:e*epochframes));
            end
        catch,
            if causal
                 smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filter(  filtwts,1,double(data(c,(e-1)*epochframes+1:e*epochframes)));
            else smoothdata(c,(e-1)*epochframes+1:e*epochframes) = filtfilt(filtwts,1,double(data(c,(e-1)*epochframes+1:e*epochframes)));
            end
        end
        if epochs == 1
            if rem(c,20) ~= 0, fprintf('.');
            else               fprintf('%d',c);
            end
        end
    end
end
fprintf('\n');


%% CAVE-eitan_office
% %{
imfolder = 'images\CAVE-eitan_office';
im_n = 6;
imfile = cell(im_n,1);
for ii = 1:im_n
    imfile{ii} = sprintf('%s\\e-%02d.jpg', imfolder, ii);
end

im = cell(im_n,1);
for ii = 1:im_n
    im{ii} = imread(imfile{ii});
end

imsize = zeros(im_n,3);

for ii = 1:im_n
    imsize(ii,:) = size(im{ii});
    if imsize(ii,1) > 720
        scale = 720/size(im{ii}, 1);
        im{ii} = imresize(im{ii}, scale);

        imsize(ii,:) = size(im{ii});
    end
end

mosaic = REW_mosaic( im, [], 0, 'persp', 0.01, imfolder );
%}


function s = bear_settings_WGP2016_test(excelPath)

s = BEARsettings(2, 'ExcelFile', excelPath);

s.frequency=3;
s.startdate='2014m5';
s.enddate='2018m12';
s.varendo='hicp gdp app 10y stockindex';
s.varexo='';
s.lags=2;
s.const=1;
s.results_path = fullfile(fileparts(mfilename('fullpath')),'results');
s.results_sub='results_test_data_WGP2016_temp';
s.results=1;
s.plot=0;
s.workspace=1;

s.favar.FAVAR=0; % augment VAR model with factors (1=yes, 0=no)

s.prior=41;
s.ar=0.8; % this sets all AR coefficients to the same prior value (if PriorExcel is equal to 0)
s.PriorExcel=0; % set to 1 if you want individual priors, 0 for default
s.priorsexogenous=0; % set to 1 if you want individual priors, 0 for default
s.lambda1=1000; % quasi-flat (diffuse) normal-wishart prior here, in the spirit of Uhlig (2005)
s.lambda2=0.5;
s.lambda3=1;
s.lambda4=1;
s.lambda5=0.001;
s.lambda6=1;
s.lambda7=0.1;
s.lambda8=1;
s.It=5000;
s.Bu=1000;
s.hogs=0;
s.bex=0;
s.scoeff=0;
s.iobs=0;
s.lrp=0;
s.priorf=100;

s.IRF=1;
s.IRFperiods=36;
s.F=0;
s.FEVD=0;
s.HD=0;
s.HDall=0;%if we want to plot the entire decomposition, all contributions (includes deterministic part)HDall
s.CF=0;
s.IRFt=4;

s.strctident.MM=0; % option for Median model (0=no (standard), 1=yes)
s.strctident.CorrelShock=''; % exact labelname of the shock defined in one of the "...res values" excel sheets, otherwise if the shock is not identified yet name it 'CorrelShock'
s.strctident.CorrelInstrument=''; % provide the IV variable in excel sheet "IV"
s.Feval=0;
s.CFt=1;
s.Fstartdate='2014q1';
s.Fenddate='2016q4';
s.Fendsmpl=0;
s.hstep=1;
s.window_size=0;
s.evaluation_size=0.5;
s.cband=0.95;
s.IRFband=0.68;
s.Fband=0.68;
s.FEVDband=0.68;
s.HDband=0.68;