


% Now, it happens that each wave, country, and question have different
% number of answers. This is not very good. In order to evolve all these
% question in the same interaction network the number of opinions must be
% the same.

% This script creates initial condition for each non empty question, 
% country, and wave with 'TotalAgents' opinions that have the same 
% classification as the original one and is in general
% simply a rescaling of the original histogram.

% The resulting original conditions are stored in a .mat file

% Another important thing that this script does is to rescale the answers.
% The original answers are integers between 1 and 10, but the models evolve
% between -1 and 1, so the answers have to be rescaled to evolve in the
% model

% Note that originaly this code was done so that different initial
% conditions would be created for different values of alpha (alpha = T_2 in
% the paper) but to recreate the results of the paper it is only necessary
% to set Alpha = 12;

clearvars 
close all

Now = datetime('now');
time_stamp = datestr(Now, 'yyyymmddHHMMSS');

% Read the real world data
load('RealDataHist.mat', 'AllWaves', 'Questions', 'CompleteCountries')

Alphas = 12; % Array of desired alphas (could be only one value)
TotalAgents = 100; % Total number of agents

Num_Q = size(AllWaves{1},1); % Number of questions
Num_C = size(AllWaves{1},2); % Number of countries

AllNorm = cell(1,length(Alphas)); % This cell will contain the new initial opinions
AllClass = cell(1,length(Alphas)); % This cell will contain the correspondign (original and new) classification

for id_alpha = 1:length(Alphas)
    % For all the alphas in 'Alpha'
    
    alpha = Alphas(id_alpha);
    
    AllWavesNorm = cell(1,3); % Initial conditions for all 3 waves
    AllWaveClass = cell(1,3); % Classification for all 3 waves

    max_count = 1e3;
    for id_wave = 1:3 % For each wave
        
        LocalHist = cell(Num_Q, Num_C); % Local histograms
        WaveClass = nan*ones(Num_Q, Num_C); % Local classifications

        for id_question = 1:Num_Q % For each question
            for id_nat = 1:Num_C % For each coubntry

                initial_Data = AllWaves{id_wave}{id_question, id_nat}; % This is the original real data

                if ~isempty(initial_Data)
                    % Of course, if it is not empty

                    repetir = 1; % There is a bit of randomness in the process, so this takes care of it
                    temp_count = 0;
                    scale_factor = 1; % If the scale factor is 1 then the histograms will have a very similar form
                    % sin some special cases that cannot happen so this
                    % requirement has to be relaxed
                    
                    while repetir&&(temp_count<max_count)
                        % Find new equivalent initial conditions
                        temp_count = temp_count + 1;
                        
                        if temp_count == ceil(max_count/2)
                            % If it seems that it is not working, then
                            % relax the 'scale_factor' criteria
                            scale_factor = 0.7;
                        end

                        % To create the initial opinions
                        
                        % 1.) Compute the number of answers in each bin
                        [N_bins,Edges] = histcounts(initial_Data,linspace(0.5, 10.5, 11));
                        
                        base_values = linspace(-1,1,11); % To compute the exact middle opinions
                        
                        count_assigned = 0; % this keeps track of the number of assigned opinions
                        ini_index = 1;
                        initial_opinions = nan*ones(TotalAgents,1);
                        for id_bin = 1:length(N_bins)
                            % For each bin
                            
                            temp_num = floor(scale_factor*N_bins(id_bin)*TotalAgents/length(initial_Data));
                            % asign 'temp_num' opinions to the bin. This is
                            % the result of rounding the scaled number of
                            % counts of that bin
                            
                            fin_index = ini_index + temp_num - 1;
                            count_assigned = count_assigned + temp_num;
                            initial_opinions(ini_index:fin_index) = ((base_values(id_bin+1)+base_values(id_bin))/2)*ones(temp_num,1);
                            % The opinions that are asigned are exactly the
                            % middle betweenthe two boundaries
                            
                            ini_index = fin_index + 1;
                        end

                        % At this point the number of assigned opinions is
                        % less than 'TotalAgents' because when computing
                        % 'temp_num' the floor is taken. So it is necessary
                        % to assign the other opinions, this will be done
                        % randomly
                        
                        random_vector = rand(1,length(N_bins));
                        while count_assigned<TotalAgents % while there are still opinions to assign
                            count_assigned = count_assigned + 1;
                            if max(random_vector)==0
                                random_vector = rand(1,length(N_bins));
                            end
                            [~,index] = max(random_vector);
                            random_vector(index) = 0;
                            initial_opinions(count_assigned) = (base_values(index) + base_values(index + 1))/2;
                            % randomly assign a value
                        end

                        % Now move the opinions randomly so they are mixed
                        new_initial_opinions = nan*ones(size(initial_opinions));
                        random_vector = rand(size(initial_opinions));
                        for id_agent = 1:length(random_vector)
                            [~,index] = max(random_vector);
                            random_vector(index) = 0;
                            new_initial_opinions(id_agent) = initial_opinions(index);
                        end
                        
                        % 'new_initial_opinions' is the new set of opinions
                        % between -1 and 1 and with 'TotalAgents' opinions

                        % Compute the classification of the old and new
                        % opinions
                        
                        hist_type_ant = HistogramClassificationEdges(initial_Data, alpha, 0, linspace(0.5, 10.5, 11));
                        hist_type_new = HistogramClassificationEdges(new_initial_opinions, alpha, 0, linspace(-1, 1, 11));

                        if hist_type_ant == hist_type_new
                            % If it is the same, then don't repeat and
                            % assign the new opinions to the corresponding
                            % cell and the corresponding classification

                            repetir = 0;

                            LocalHist{id_question, id_nat} = new_initial_opinions;
                            WaveClass(id_question, id_nat) = hist_type_new;

                        end
                    end

                    if (hist_type_ant~= hist_type_new)&&repetir

                        hist_type_ant = HistogramClassificationEdges(initial_Data, alpha, 1, linspace(0.5, 10.5, 11));
                        hist_type_new = HistogramClassificationEdges(new_initial_opinions, alpha, 1, linspace(-1, 1, 11));

                        disp(['Esto no deberia pasar wave ' num2str(id_wave) ' question ' num2str(id_question) ' country ' num2str(id_nat)])
                        
                    end

                end

            end
        end

        % Put the resulting new initial opinions and classification in the
        % cells
        
        AllWavesNorm{id_wave} = LocalHist;
        AllWaveClass{id_wave} = WaveClass;

    end
    

    % +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
    % +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

    % Modification:

    % Create two articifial waves, to facilitate the working of the code so
    % that Wave_1 = [Wave_5, Wave_6] and Wave_2 = [Wave_6, Wave_7];


    Wave1Norm = cell(Num_Q, (2*Num_C));
    Wave2Norm = cell(Num_Q, (2*Num_C));

    Wave1Class = nan*ones(Num_Q, (2*Num_C));
    Wave2Class = nan*ones(Num_Q, (2*Num_C));

    for id_row = 1:Num_Q
        for id_col = 1:Num_C
            Wave1Norm{id_row,id_col} = AllWavesNorm{1}{id_row,id_col};
            Wave1Norm{id_row,id_col+Num_C} = AllWavesNorm{2}{id_row,id_col};

            Wave2Norm{id_row,id_col} = AllWavesNorm{2}{id_row,id_col};
            Wave2Norm{id_row,id_col+Num_C} = AllWavesNorm{3}{id_row,id_col};

            Wave1Class(id_row,id_col) = AllWaveClass{1}(id_row,id_col);
            Wave1Class(id_row,id_col+Num_C) = AllWaveClass{2}(id_row,id_col);

            Wave2Class(id_row,id_col) = AllWaveClass{2}(id_row,id_col);
            Wave2Class(id_row,id_col+Num_C) = AllWaveClass{3}(id_row,id_col);
        end
    end


    % And do that for every value of alpha
   
    AllNorm{id_alpha} = {Wave1Norm, Wave2Norm};
    AllClass{id_alpha} = {Wave1Class, Wave2Class};
    
end

save(['./Data/Initial_Data/InitialOpinions_' num2str(TotalAgents) '_agents.mat'], 'AllNorm', 'AllClass', 'Num_Q', 'Num_C', 'Alphas', 'time_stamp')
% Save the results. The new variables that are created are 

% 'AllNorm' which for each value of Alpha contains the initial opinions
% with TotalAgent opinions that for each wave, country and question give
% the same classification and more over produce a histogram similar to the
% original one

% 'AllClass' has the correspondig classification of the original opinions
% (and the new ones) for the corresponding values of alpha

% 'Num_Q' number of questions

% 'Num_C' number of countries

% 'Alpha' array of the possible values of alpha

% Now rearrange the initial opinions so that they can be used in the
% computation of Table B


AllInitialOpinions = cell(Num_Q*Num_C*3*2,1);

IO_counter = 0;
for id_wave = 1:3
    for id_row = 1:Num_Q
        for id_col = 1:Num_C

            IO_counter = IO_counter + 1;
            AllInitialOpinions{IO_counter} = AllWavesNorm{id_wave}{id_row,id_col};

            IO_counter = IO_counter + 1;
            AllInitialOpinions{IO_counter} = -AllWavesNorm{id_wave}{id_row,id_col};

        end
    end
end

GeneralAgreement = GeneralAgreementComputation(AllInitialOpinions);
GeneralAgreement = round(GeneralAgreement,1);

IO_counter_2 = 0;

for id_row = 1:IO_counter
    if GeneralAgreement(id_row,1)>=-(GeneralAgreement(id_row,2))
        IO_counter_2 = IO_counter_2 + 1;
    end
end

NewAllInitialOpinions = cell(IO_counter_2,1);

IO_counter_2 = 0;

for id_row = 1:IO_counter
    if GeneralAgreement(id_row,1)>=-(GeneralAgreement(id_row,2))
        IO_counter_2 = IO_counter_2 + 1;
        NewAllInitialOpinions{IO_counter_2} = AllInitialOpinions{id_row};
    end
end

AllInitialOpinions = NewAllInitialOpinions;

GeneralAgreement = GeneralAgreementComputation(AllInitialOpinions);
GeneralAgreement = round(GeneralAgreement,1);


num_IO = size(AllInitialOpinions,1);
unique_agreement = size(unique(GeneralAgreement, 'rows'),1);

if ~(unique_agreement == num_IO)

    NewAllInitialOpinions = cell(unique_agreement,1);
    [~,unique_index,~] = unique(GeneralAgreement, 'rows');

    for id_row = 1:unique_agreement
        NewAllInitialOpinions{id_row} = AllInitialOpinions{unique_index(id_row)};
    end

end

AllInitialOpinions = NewAllInitialOpinions;

num_IO = size(AllInitialOpinions,1);
GeneralAgreement = GeneralAgreementComputation(AllInitialOpinions);
GeneralAgreement = round(GeneralAgreement,1);
unique_agreement = size(unique(GeneralAgreement, 'rows'),1);

if ~(num_IO == unique_agreement)
    disp('There is a problem')
    keyboard
end



NewAllInitialOpinions = cell(2*size(AllInitialOpinions,1),1);

IO_counter = 0;
for id_row = 1:size(AllInitialOpinions,1)
    IO_counter = IO_counter + 1;
    NewAllInitialOpinions{IO_counter} = AllInitialOpinions{id_row};

    IO_counter = IO_counter + 1;
    NewAllInitialOpinions{IO_counter} = -AllInitialOpinions{id_row};
end

AllInitialOpinions = NewAllInitialOpinions;

num_IO = size(AllInitialOpinions,1);
GeneralAgreement = GeneralAgreementComputation(AllInitialOpinions);
GeneralAgreement = round(GeneralAgreement,1);
unique_agreement = size(unique(GeneralAgreement, 'rows'),1);

if ~(unique_agreement == num_IO)

    NewAllInitialOpinions = cell(unique_agreement,1);
    [~,unique_index,~] = unique(GeneralAgreement, 'rows');

    random_vector = rand(size(unique_index));
    [~,sort_index] = sort(random_vector);

    for id_row = 1:unique_agreement
        NewAllInitialOpinions{id_row} = AllInitialOpinions{unique_index(sort_index(id_row))};
    end

end

AllInitialOpinions = NewAllInitialOpinions;


save(['LinearInitialOpinions_' num2str(TotalAgents) '_agents.mat'], 'AllInitialOpinions', 'time_stamp')














