function [model] = main_CGM_real_v1(prob, param,  maxiter, doTest)
%main function of CGM, which learns a graph and model parameters at the
%same time.
%parameters:
%prob.X: training data;
%prob.y: training label;
%prob.X_te: testing data;
%prob.y_te: testing label;
%maxiter: number of maximum iterations;
%param: parameters used in the subproblem optimization;
%param.C: default value 1.0;
%param.B: number of cliques added per iteration;
%param.lambda: default value 0.00001; 
%param.max_iter: maximum iterations for subproblem optimization, default value 40;
%param.out_put_loss: output loss or not, default value 1;
%param.update_close_form: choose different updating rule, default value 1.
if nargin<4
    doTest = 1; %do prediction on testing data. This requires input of prob.X_te and prob.y_te
end
if nargin<3
    maxiter = 10;
end


if (doTest == 1)&&(size(prob.X_te,1)==0)
    %when there are no testing data, setting doTest to 0;
    doTest = 0; 
end
%%


model.G = [];
model.alpha = zeros(prob.num_inst,1);
model.num_cliques = 0;
obj_hist_all = [];


G_possible = list_possible_edge(prob.num_label);
prob.G_possible = G_possible;
Y_infer = -prob.y + 1;
% Y_infer(Y_infer>0) = 0;
% Y_infer(Y_infer<0) = 1;
[G, score_sort, G_possible] = most_violated_cliques_v_test(model.alpha+1, prob, prob.y, Y_infer, param.B);
prob.G_possible = G_possible;
% G = [1 2; 1 3; 1 4; 1 5];
model.G = [model.G; G];
model.num_cliques = size(model.G,1);
prob.num_cliques = size(model.G,1);
model.w = zeros(2*prob.num_label+4*model.num_cliques,prob.Dim);

%an example of G = [1 2; 1 3; 1 4; 1 5];
prob.G_possible = G_possible;
model.G = [model.G; G];
model.num_cliques = size(model.G,1);
prob.num_cliques = size(model.G,1);
model.w = zeros(2*prob.num_label+4*model.num_cliques,prob.Dim);%BCD_prox_gradient_CGM_sqBCD_prox_gradient_CGM_real


%train without edges
[w_f, alpha, alpha_v,obj_hist,Y_infer] = PCD_SSVM(prob,  model, param);
obj_hist_all = [obj_hist_all;obj_hist];
model.w = w_f;

if doTest
for j = 1:size(prob.X_te,1)
     x_inst = prob.X_te(j,:);
     [y_infer]= predict_most_vialated_feature_mapping_v1(prob, model.G, model.w, x_inst);
     y_pred(j,:) = y_infer;
end
[HammingLoss, Macro_F1, Micro_F1, Macro_Precision, Micro_Precision,  Macro_Recall, Micro_Recall, F_all, Precision_all, Recall_all] = compute_measures(y_pred, prob.y_te);
result.HammingLoss(1) = HammingLoss;
result.Macro_F1(1) = Macro_F1;
result.Micro_F1(1) = Micro_F1;
result.Precision_all(1) = max(Precision_all,Macro_Precision);
result.Recall_all(1) = Macro_Recall;
end


[G, ~, G_possible] = most_violated_cliques_v_test(alpha_v, prob,prob.y,Y_infer, param.B);
prob.G_possible = G_possible;
model.G = [model.G;G];
model.num_cliques = size(model.G,1);
prob.num_cliques = size(model.G,1);

total_edge = 13;
maxiter = min(maxiter,round(total_edge/param.B)-2);
for iter = 1:maxiter
    model.w = [w_f; zeros(4*size(G,1),prob.Dim)];
    [w_f, alpha, alpha_v,obj_hist,Y_infer, tr_hamming] = PCD_SSVM(prob,  model, param);%BCD_prox_gradient_CGM
    obj_hist_all = [obj_hist_all;obj_hist];
    model.w = w_f;

    if doTest
    for j = 1:size(prob.X_te,1)
     x_inst = prob.X_te(j,:);
     [y_infer]= predict_most_vialated_feature_mapping_v1(prob, model.G, model.w, x_inst);
     y_pred(j,:) = y_infer;
    end
    [HammingLoss, Macro_F1, Micro_F1, Macro_Precision, Micro_Precision,  Macro_Recall, Micro_Recall, F_all, Precision_all, Recall_all] = compute_measures(y_pred, prob.y_te);
    
    result.HammingLoss(iter+1) = HammingLoss
    result.Macro_F1(iter+1) = Macro_F1;
    result.Micro_F1(iter+1) = Micro_F1;
    result.Precision_all(iter+1) = Precision_all;
    result.Recall_all(iter+1) = Macro_Recall;
    end
    
    [G, ~,G_possible] = most_violated_cliques_v_test(alpha_v, prob,prob.y,Y_infer, param.B);
    prob.G_possible = G_possible;
    model.G = [model.G;G];
    model.num_cliques = size(model.G,1);
end

if doTest
    model.result = result;
end

model.obj_hist_all = obj_hist_all;
model.train_hammingloss = tr_hamming;
