function [Metric,y_predict_real,y_predict_bin,model] = SIDLEv1(X_train,y_train,X_test,y_test,k,numLabel,lambda,write_file)
%KAFADLV1 此处显示有关此函数的摘要
%   此处显示详细说明
    if nargin<8
        write_file.file_id = 1;%standard output (the screen)
        write_file.head_str = '   ';
        write_file.verbose = 1;%with outputs
    end
    if nargin<6
        lambda = 2^-3;
    end
    if nargin<5
        k = 10;
    end

    %basic functions called by CLIM
    addpath('basic_functions');
    %optimization function
    addpath('minFunc');
    addpath('minFunc/compiled');

    all_fid = write_file.file_id;
    head_str = write_file.head_str;
    verbose = write_file.verbose;

    num_tr = size(X_train,1);%number of training samples
    X_train = [ones(num_tr,1),X_train];%add bias
    num_te = size(X_test,1);%number of testing samples
    X_test = [ones(num_te,1),X_test];%add bias
    num_dim = length(numLabel);%number of dimensions
    num_attr = size(X_train,2);%number of input attributes

    %% First time prediction
    %initialization
    if verbose
        temp_str = [head_str,'(1) First time prediction (',disp_time(clock,0),')...'];
        fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
    end
    y_pre_init_tr_r = zeros(size(y_train));%y_predict_initialization_train_real
    y_pre_init_tr_b = zeros(size(y_train));%y_predict_initialization_train_binary
    RL_init_tr = zeros(num_dim,1);%RankingLoss_initialization_train
    theta_init = cell(num_dim,1);%theta_initialization
    TH_init = zeros(num_dim,1);%threshold_initialization

    for dd=1:num_dim
        %label index for dd-th dimension
        idx_dim_b = sum(numLabel(1:dd-1))+1;
        idx_dim_e = sum(numLabel(1:dd));
        %label matrix for dd-th dimension
        y_train_dd = y_train(:,idx_dim_b:idx_dim_e);
        %gradient descent
        theta_0 = rand(num_attr,numLabel(dd)-1)*0.001;%d*(q-1)
        options = struct('MaxIter', 200);
        theta_vec = minFunc(@costFunc, theta_0(:), options, X_train, y_train_dd, lambda);
        theta_mtx = reshape(theta_vec,num_attr,[]);%d*(q-1)
        Theta = [theta_mtx,zeros(num_attr,1)];%d*q
        theta_init{dd} = Theta;
        linR = X_train*Theta;%m*q
        eR = exp(linR);%m*q
        eR_sumrow = sum(eR,2);%m*1
        eR_sum_row_mtx = repmat(eR_sumrow,1,numLabel(dd));%m*q
        softR = eR./eR_sum_row_mtx;%m*q, predicted label matrix in probability style
        %ranking loss over training set
        RL_init_tr(dd) = Ranking_loss(softR',y_train_dd');
        %save predicted label matrix in probability style for training examples
        y_pre_init_tr_r(:,idx_dim_b:idx_dim_e) = softR;
        %determine threshold with MAP rule
        [TH_init(dd), y_predict_bin] = THfunc(softR, y_train_dd);
        %save predicted label matrix in binary style for training examples
        y_pre_init_tr_b(:,idx_dim_b:idx_dim_e) = y_predict_bin;
    end

    %find kNN set of the prediction
    % [pre_train_stats,pre_train_idx] = kNN_stats(y_pre_init_tr_r,y_pre_init_tr_r,y_train,k,numLabel);
    
    %add kNN statistics as augmented feature
    % X_train_aug = [X_train,pre_train_stats];

    %train data with augmented feature
    if verbose
        temp_str = [head_str,'(2) Training phase: the second&third phase (',disp_time(clock,0),')...'];
        fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
    end
    y_pre_main_tr_r = y_pre_init_tr_r;%y_predict_main_train_real
    y_pre_main_tr_b = y_pre_init_tr_b;%y_predict_main_train_binary
    theta_main = theta_init;
    TH_main = TH_init;
    max_loop = 50;
    RL_main_train = zeros(max_loop+1,num_dim);
    RL_main_train(1,:) = RL_init_tr;
    if verbose
        temp_str = [head_str,'  loop = 0: '];
        for idisp=1:num_dim
            temp_str = [temp_str, num2str(RL_main_train(1,idisp),'%7.6f'), ', '];
        end
        temp_str = [temp_str, '(',disp_time(clock,0),')'];
        fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
    end
    TH_main_loop = cell(max_loop+1,1);
    TH_main_loop{1} = TH_main;
    theta_main_loop = cell(max_loop+1,1);
    theta_main_loop{1} = theta_main;
    for loop=1:max_loop
        is_update = false;
        [pre_train_stats1,kNN_idx1] = kNN_stats(X_train,X_train,y_train,k,numLabel);
        [pre_train_stats2,kNN_idx2] = kNN_stats(y_pre_main_tr_r,y_pre_main_tr_r,y_train,k,numLabel);
        % X_train_aug1 = aug_bias(X_train,y_train,kNN_idx1,k,numLabel);
        X_train_aug1 = pre_train_stats1;
        % X_train_aug2 = aug_bias(y_pre_main_tr_r,y_train,kNN_idx2,k,numLabel);
        X_train_aug2 = pre_train_stats2;
        X_train_aug = [X_train,normalize(X_train_aug1)+normalize(X_train_aug2)+y_pre_main_tr_r];
        % X_train_aug = [X_train,normalize(X_train_aug2)];
        RL_main_train(loop+1,:) = RL_main_train(loop,:);
        for dd=1:num_dim
            %label index for dd-th dimension
            idx_dim_b = sum(numLabel(1:dd-1))+1;
            idx_dim_e = sum(numLabel(1:dd));
            %label matrix for dd-th dimension
            y_train_dd = y_train(:,idx_dim_b:idx_dim_e);
            %gradient descent
            num_attr_aug = size(X_train_aug,2);
            theta_0 = rand(num_attr_aug,numLabel(dd)-1)*0.001;
            options = struct('MaxIter', 200);
            theta_vec=minFunc(@costFunc, theta_0(:), options, X_train_aug, y_train_dd, lambda);
            theta_mtx = reshape(theta_vec,num_attr_aug,[]);
            Theta = [theta_mtx,zeros(num_attr_aug,1)];
            linR = X_train_aug*Theta;%m*q
            eR = exp(linR);%m*q
            eR_sumrow = sum(eR,2);%m*1
            eR_sum_row_mtx = repmat(eR_sumrow,1,numLabel(dd));%m*q
            softR = eR./eR_sum_row_mtx;%m*q, predicted label matrix in probability style
            %ranking loss over training set
            RL_main = Ranking_loss(softR',y_train_dd');
            if RL_main<RL_main_train(loop+1,dd)
                is_update = true;
                %update training results
                RL_main_train(loop+1,dd) = RL_main;
                y_pre_main_tr_r(:,idx_dim_b:idx_dim_e) = softR;
                theta_main{dd} = Theta;

                [TH_main(dd), y_predict_bin] = THfunc(softR, y_train_dd);
                y_pre_main_tr_b(:,idx_dim_b:idx_dim_e) = y_predict_bin;
            end
        end
        theta_main_loop{loop+1} = theta_main;
        TH_main_loop{loop+1} = TH_main;
        if verbose
            if loop<10
                temp_str = [head_str,'  loop = ',num2str(loop),': '];
            else
                temp_str = [head_str,'  loop =', num2str(loop),': '];
            end
            for idisp=1:num_dim
                temp_str = [temp_str, num2str(RL_main_train(loop+1,idisp),'%7.6f'), ', '];
            end
            temp_str = [temp_str, '(',disp_time(clock,0),')'];
            fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
        end
        if ~is_update
            if verbose
                temp_str = [head_str,'  break at loop = ', num2str(loop), ' (',disp_time(clock,0),')'];
                fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
            end
            break;
        end
    end%for loop=1:max_loop

    %% Testing
    if verbose
        temp_str = [head_str,'(3) Testing phase (',disp_time(clock,0),')...'];
        fprintf(all_fid,temp_str);fprintf(all_fid,'\n');
    end
    
    y_pre_init_te_r = zeros(num_te,sum(numLabel));%y_predict_initialization_test_real
    y_pre_init_te_b = zeros(num_te,sum(numLabel));%y_predict_initialization_test_binary
    for dd=1:num_dim
        %label index for dd-th dimension
        idx_dim_b = sum(numLabel(1:dd-1))+1;
        idx_dim_e = sum(numLabel(1:dd));
        %Obtain predicted label matrix for testing examples
        Theta = theta_main_loop{1}{dd};%or theta_init{dd};
        linR = X_test*Theta;%m*q
        eR = exp(linR);%m*q
        eR_sumrow = sum(eR,2);%m*1
        eR_sum_row_mtx = repmat(eR_sumrow,1,numLabel(dd));%m*q
        softR = eR./eR_sum_row_mtx;%m*q
        %save predicted label matrix in probability style for testing examples
        y_pre_init_te_r(:,idx_dim_b:idx_dim_e) = softR;
        %save predicted label matrix in binary style for testing examples
        y_pre_init_te_b(:,idx_dim_b:idx_dim_e) = (softR>TH_main_loop{1}(dd))+0;%or (softR>TH_init(dd))+0;
    end
    
    max_loop_te = loop;
    y_pre_main_te_r = y_pre_init_te_r;%y_predict_main_test_real
    y_pre_main_te_b = y_pre_init_te_b;%y_predict_main_test_binary
    for loop=1:max_loop_te
        [pre_test_stats1,kNN_idx3] = kNN_stats(X_train,X_test,y_train,k,numLabel);
        [pre_test_stats2,kNN_idx4] = kNN_stats(y_pre_main_tr_r,y_pre_main_te_r,y_train,k,numLabel);
        % X_test_aug1 = aug_bias(X_test,y_train,kNN_idx3,k,numLabel);
        X_test_aug1 = pre_test_stats1;
        % X_test_aug2 = aug_bias(y_pre_main_te_r,y_train,kNN_idx4,k,numLabel);
        X_test_aug2 = pre_test_stats2;
        X_test_aug = [X_test,normalize(X_test_aug1)+normalize(X_test_aug2)+y_pre_main_te_r];
        % X_test_aug = [X_test,normalize(X_test_aug2)];
        for dd=1:num_dim
            %label index for dd-th dimension
            idx_dim_b = sum(numLabel(1:dd-1))+1;
            idx_dim_e = sum(numLabel(1:dd));
            %update testing results
            if RL_main_train(loop+1,dd)<RL_main_train(loop,dd)
                Theta = theta_main_loop{loop+1}{dd};
                linR = X_test_aug*Theta;%m*q
                eR = exp(linR);%m*q
                eR_sumrow = sum(eR,2);%m*1
                eR_sum_row_mtx = repmat(eR_sumrow,1,numLabel(dd));%m*q
                softR = eR./eR_sum_row_mtx;%m*q
                %save predicted label matrix in probability style for testing examples
                y_pre_main_te_r(:,idx_dim_b:idx_dim_e) = softR;
                %save predicted label matrix in binary style for testing examples
                y_pre_main_te_b(:,idx_dim_b:idx_dim_e) = (softR>TH_main_loop{loop+1}(dd))+0;
            end
        end
    end
    
    Metric = MDML_metric(y_pre_main_te_r, y_test, y_pre_main_te_b, numLabel);
    y_predict_real = y_pre_main_te_r;
    y_predict_bin = y_pre_main_te_b;
    model.theta = theta_main_loop(1:max_loop_te+1);
    model.TH = TH_main_loop(1:max_loop_te+1);
    model.RL = RL_main_train(1:max_loop_te+1);
end

