% Arrow project

clear
clc

%% Generate data

nCitizens = 5; 

p1 = [[1 2 3 4]',[1 2 3 4]',[2 1 3 4]',[2 3 4 1]',[3 4 1 2]'];
p2 = [[1 2 3 4]',[1 2 3 4]',[2 1 3 4]',[2 4 3 1]',[3 4 1 2]'];
p3 = [[1 2 3 4]',[1 3 4 2]',[2 1 3 4]',[3 2 1 4]',[4 2 3 1]'];
p4 = [[1 2 3 4]',[1 4 3 2]',[2 1 3 4]',[3 2 1 4]',[4 2 3 1]'];
p5 = [[1 2 3 4]',[1 2 3 4]',[2 3 4 1]',[4 1 3 2]',[4 3 2 1]'];
p6 = [[1 2 3 4]',[1 2 3 4]',[3 2 4 1]',[4 1 3 2]',[4 2 3 1]'];

prefs = cat(3, p1, p2, p3, p4, p5, p6);





%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%      Get outcomes                               %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




%% Scoring rule outcomes

[nOptions, nVoters, nRankings] = size(prefs);

pref = permute(prefs,[1 3 2]);




nScoringResolution = 101;
sLower = -5;
s = linspace(sLower, 5, nScoringResolution);

nScoringRules = nScoringResolution;


pointsScore = zeros(nRankings * nCitizens, nOptions);

[pointsScore(:, 1), ~] = find(pref == 1);
[pointsScore(:, 2), ~] = find(pref == 2);
[pointsScore(:, 3), ~] = find(pref == 3);
[pointsScore(:, 4), ~] = find(pref == 4);

pointsScore = pointsScore';
pointsScore = reshape(pointsScore, nOptions, nRankings, nCitizens);

generalScoreWinner = zeros(nRankings, nScoringRules);
generalScoreWin1 = zeros(nRankings, nScoringRules);
generalScoreWin2 = zeros(nRankings, nScoringRules);
generalScoreWin3 = zeros(nRankings, nScoringRules);
generalScoreWin4 = zeros(nRankings, nScoringRules);

tieGeneralScore = zeros(nRankings, nScoringRules);

generalScoreAll = zeros(nOptions, nRankings, nCitizens, nScoringResolution);

for scoreIndex = 1:nScoringResolution 
    
    s1 = (1/3)^(exp(s(scoreIndex))/exp(0));
    s2 = (2/3)^(exp(s(scoreIndex))/exp(0));
        
    weights = [1, s2, s1, 0];
    generalScore = weights(1) * (pointsScore == 1) ...
                   + weights(2) * (pointsScore == 2) ...
                   + weights(3) * (pointsScore == 3) ...
                   + weights(4) * (pointsScore == 4) ;
               
    generalScoreAll(:,:,:,scoreIndex) = generalScore; 

    generalScoreCount = sum(generalScore, 3);
    [maxGeneralScore, generalScoreWinnerS] = max(generalScoreCount, [], 1);

    tol = 1e-10;
    generalScoreWin1(:, scoreIndex) = generalScoreCount(1,:) >= maxGeneralScore -tol;
    generalScoreWin2(:, scoreIndex) = generalScoreCount(2,:) >= maxGeneralScore -tol;
    generalScoreWin3(:, scoreIndex) = generalScoreCount(3,:) >= maxGeneralScore -tol;
    generalScoreWin4(:, scoreIndex) = generalScoreCount(4,:) >= maxGeneralScore -tol;

    winSetGeneralScore = repmat(maxGeneralScore, nOptions, 1) == generalScoreCount;
    winNumGeneralScore = sum(winSetGeneralScore, 1);

    tieGeneralScore(:, scoreIndex) = winNumGeneralScore > 1; 
end


 
scoreWinner = 1 * generalScoreWin1 + ...
                 2 * generalScoreWin2 + ...
                 3 * generalScoreWin3 + ...
                 4 * generalScoreWin4;
             
scoreTie = (generalScoreWin1 + ...
               generalScoreWin2 + ...
               generalScoreWin3 + ...
               generalScoreWin4) > 1;
           
scoreWinner = (scoreTie == 0) .* scoreWinner + ...
               (scoreTie == 1) .* (10);

scoreWinnerSet = 99*ones(nRankings,4);             
for i = 1 : nRankings             
    u = unique(scoreWinner(i,:));
    scoreWinnerSet(i, 1:numel(u)) = u;
end


resolute = max(tieGeneralScore, [], 2) == 0;




%% BadScoring rule outcomes

[nOptions, nVoters, nRankings] = size(prefs);

pref = permute(prefs,[1 3 2]);




nBadScoringResolution = 101;
sLower = -5;
s = linspace(sLower, 5, nBadScoringResolution);

nBadScoringRules = nBadScoringResolution;


pointsBadScore = zeros(nRankings * nCitizens, nOptions);

[pointsBadScore(:, 1), ~] = find(pref == 1);
[pointsBadScore(:, 2), ~] = find(pref == 2);
[pointsBadScore(:, 3), ~] = find(pref == 3);
[pointsBadScore(:, 4), ~] = find(pref == 4);

pointsBadScore = pointsBadScore';
pointsBadScore = reshape(pointsBadScore, nOptions, nRankings, nCitizens);

generalBadScoreWinner = zeros(nRankings, nBadScoringRules);
generalBadScoreWin1 = zeros(nRankings, nBadScoringRules);
generalBadScoreWin2 = zeros(nRankings, nBadScoringRules);
generalBadScoreWin3 = zeros(nRankings, nBadScoringRules);
generalBadScoreWin4 = zeros(nRankings, nBadScoringRules);

tieGeneralBadScore = zeros(nRankings, nBadScoringRules);

generalBadScoreAll = zeros(nOptions, nRankings, nCitizens, nBadScoringResolution);

for BadScoreIndex = 1:nBadScoringResolution 
    
    s1 = (1/3)^(exp(s(BadScoreIndex))/exp(0));
    s2 = (2/3)^(exp(s(BadScoreIndex))/exp(0));
        
    weights = [0, s1, s2, 1];
    generalBadScore = weights(1) * (pointsBadScore == 1) ...
                   + weights(2) * (pointsBadScore == 2) ...
                   + weights(3) * (pointsBadScore == 3) ...
                   + weights(4) * (pointsBadScore == 4) ;
               
    generalBadScoreAll(:,:,:,BadScoreIndex) = generalBadScore; 

    generalBadScoreCount = sum(generalBadScore, 3);
    [maxGeneralBadScore, generalBadScoreWinnerS] = max(generalBadScoreCount, [], 1);

    tol = 1e-10;
    generalBadScoreWin1(:, BadScoreIndex) = generalBadScoreCount(1,:) >= maxGeneralBadScore -tol;
    generalBadScoreWin2(:, BadScoreIndex) = generalBadScoreCount(2,:) >= maxGeneralBadScore -tol;
    generalBadScoreWin3(:, BadScoreIndex) = generalBadScoreCount(3,:) >= maxGeneralBadScore -tol;
    generalBadScoreWin4(:, BadScoreIndex) = generalBadScoreCount(4,:) >= maxGeneralBadScore -tol;

    winSetGeneralBadScore = repmat(maxGeneralBadScore, nOptions, 1) == generalBadScoreCount;
    winNumGeneralBadScore = sum(winSetGeneralBadScore, 1);

    tieGeneralBadScore(:, BadScoreIndex) = winNumGeneralBadScore > 1; 
end


 
BadScoreWinner = 1 * generalBadScoreWin1 + ...
                 2 * generalBadScoreWin2 + ...
                 3 * generalBadScoreWin3 + ...
                 4 * generalBadScoreWin4;
             
BadScoreTie = (generalBadScoreWin1 + ...
               generalBadScoreWin2 + ...
               generalBadScoreWin3 + ...
               generalBadScoreWin4) > 1;
           
BadScoreWinner = (BadScoreTie == 0) .* BadScoreWinner + ...
               (BadScoreTie == 1) .* (10);

BadScoreWinnerSet = 99*ones(nRankings,4);             
for i = 1 : nRankings             
    u = unique(BadScoreWinner(i,:));
    BadScoreWinnerSet(i, 1:numel(u)) = u;
end


resolute = max(tieGeneralBadScore, [], 2) == 0;





%% Get Condorcet outcome

% Get binary comparisons

bin1beats2 = find(pref == 1) < find(pref == 2);
bin1beats2 = reshape(bin1beats2, nRankings, nCitizens);
bin2beats1 = 1 - bin1beats2;

bin1beats3 = find(pref == 1) < find(pref == 3);
bin1beats3 = reshape(bin1beats3, nRankings, nCitizens);
bin3beats1 = 1 - bin1beats3;

bin1beats4 = find(pref == 1) < find(pref == 4);
bin1beats4 = reshape(bin1beats4, nRankings, nCitizens);
bin4beats1 = 1 - bin1beats4;

bin2beats3 = find(pref == 2) < find(pref == 3);
bin2beats3 = reshape(bin2beats3, nRankings, nCitizens);
bin3beats2 = 1 - bin2beats3;

bin2beats4 = find(pref == 2) < find(pref == 4);
bin2beats4 = reshape(bin2beats4, nRankings, nCitizens);
bin4beats2 = 1 - bin2beats4;

bin3beats4 = find(pref == 3) < find(pref == 4);
bin3beats4 = reshape(bin3beats4, nRankings, nCitizens);
bin4beats3 = 1 - bin3beats4;

% Get winner in each binary comparison

vote1beats2 = sum(bin1beats2, 2) >= nCitizens/2;
vote2beats1 = sum(bin2beats1, 2) >= nCitizens/2;
vote1beats3 = sum(bin1beats3, 2) >= nCitizens/2;
vote3beats1 = sum(bin3beats1, 2) >= nCitizens/2;
vote1beats4 = sum(bin1beats4, 2) >= nCitizens/2;
vote4beats1 = sum(bin4beats1, 2) >= nCitizens/2;
vote2beats3 = sum(bin2beats3, 2) >= nCitizens/2;
vote3beats2 = sum(bin3beats2, 2) >= nCitizens/2;
vote2beats4 = sum(bin2beats4, 2) >= nCitizens/2;
vote4beats2 = sum(bin4beats2, 2) >= nCitizens/2;
vote3beats4 = sum(bin3beats4, 2) >= nCitizens/2;
vote4beats3 = sum(bin4beats3, 2) >= nCitizens/2;

condorcetWins1 = vote1beats2 + vote1beats3 + vote1beats4;
condorcetWins2 = vote2beats1 + vote2beats3 + vote2beats4;
condorcetWins3 = vote3beats1 + vote3beats2 + vote3beats4;
condorcetWins4 = vote4beats1 + vote4beats2 + vote4beats3;

condorcetWins = [condorcetWins1 condorcetWins2 condorcetWins3 condorcetWins4];

[maxCondorcetWins, ~] = max(condorcetWins, [], 2); 

condorcetWin1 = maxCondorcetWins == condorcetWins1;
condorcetWin2 = maxCondorcetWins == condorcetWins2;
condorcetWin3 = maxCondorcetWins == condorcetWins3;
condorcetWin4 = maxCondorcetWins == condorcetWins4;

condorcetWinner = 1 * condorcetWin1 + ...
                  2 * condorcetWin2 + ...
                  3 * condorcetWin3 + ...
                  4 * condorcetWin4;

winSet = [condorcetWin1 condorcetWin2 condorcetWin3 condorcetWin4];
condorcetWinNum = sum(winSet, 2);

condorcetTie = condorcetWinNum > 1; 

condorcetWinner = (condorcetTie == 0) .* condorcetWinner + ...
                  (condorcetTie == 1) .* (-1);


%% Plurality runoff

% In case of second-place tie, it must be a three-way tie. 
% In this case, just select the plurality winner. 

pluralityRunoffWinner = zeros(1, nRankings);


for r = 1 : nRankings

    profile = squeeze(pref(:, r, :));
        
    votes1 = sum(profile(1,:) == 1); 
    votes2 = sum(profile(1,:) == 2); 
    votes3 = sum(profile(1,:) == 3); 
    votes4 = sum(profile(1,:) == 4); 
    

    [firstRoundMax, firstRoundWinner] = max([votes1, votes2, votes3, votes4]);
    [firstRoundMin, ~] = min([votes1, votes2, votes3, votes4]);
    
    
    twoTwoTie = (votes1 == 2 & votes2 == 2) ...
              | (votes1 == 2 & votes3 == 2) ...
              | (votes1 == 2 & votes4 == 2) ...
              | (votes2 == 2 & votes3 == 2) ...
              | (votes2 == 2 & votes4 == 2) ...
              | (votes3 == 2 & votes4 == 2);
   
    
    if firstRoundMax >= 3
        pluralityRunoffWinner(r) = firstRoundWinner;
    elseif twoTwoTie == 1
        if     (votes1 == 2 && votes2 == 2)
            profile = profile(profile == 1 | profile == 2);
            profile = reshape(profile, 2, 5);
        elseif (votes1 == 2 && votes3 == 2)
            profile = profile(profile == 1 | profile == 3);
            profile = reshape(profile, 2, 5);
        elseif (votes1 == 2 && votes4 == 2)
            profile = profile(profile == 1 | profile == 4);
            profile = reshape(profile, 2, 5);
        elseif (votes2 == 2 && votes3 == 2)
            profile = profile(profile == 2 | profile == 3);
            profile = reshape(profile, 2, 5);
        elseif (votes2 == 2 && votes4 == 2)
            profile = profile(profile == 2 | profile == 4);
            profile = reshape(profile, 2, 5);
        elseif (votes3 == 2 && votes4 == 2)
            profile = profile(profile == 3 | profile == 4);
            profile = reshape(profile, 2, 5);
        end


        votes1 = sum(profile(1,:) == 1); 
        votes2 = sum(profile(1,:) == 2); 
        votes3 = sum(profile(1,:) == 3); 
        votes4 = sum(profile(1,:) == 4); 

        [~, secondRoundWinner] = max([votes1, votes2, votes3, votes4]);      
        
        pluralityRunoffWinner(r) = secondRoundWinner;
    else
        pluralityRunoffWinner(r) = 0;
    end
    
end

        


%% Scoring runoff

if 0 
    
    
    generalScoreAll = squeeze(sum(generalScoreAll, 3)); 
    scoreRanks = zeros(size(generalScoreAll));
    for i = 1 : nRankings
        for s = 1 : nScoringRules
            [~,scoreRanks(:,i,s)]=ismember(generalScoreAll(:,i,s),sort(generalScoreAll(:,i,s),'descend'));
        end
    end


    % Drop option ranked last
    keepOption = scoreRanks ~= 4; 
    keepOption = reshape(keepOption, nOptions, nRankings, 1, nScoringRules);
    keepOption = repmat(keepOption, 1, 1, 5, 1);
    dropOption = scoreRanks == 4; 
    dropOption = reshape(dropOption, nOptions, nRankings, 1, nScoringRules);
    dropOption = repmat(dropOption, 1, 1, 5, 1);

    % New preference profile, in which the preference for the dropped option is
    % set to 5: 
    prefKept = pref.*keepOption + (1+nOptions) * dropOption; 

    % Relabel preference ranks to 1 and 2, such that the unavailable option
    % receives preference 3 for all Choosers. 
    for i = 1 : nRankings
        for s = 1 : nScoringRules
            for j = 1 : 5 
                [~,prefKept(:,i,j,s)]=ismember(prefKept(:,i,j,s),sort(prefKept(:,i,j,s),'ascend'));
            end
        end
    end
    
    

    % Rerun scoring on altered profile
    
    pref = prefKept


    pointsScore = zeros(nRankings * nCitizens, nOptions, nScoringRules);
    
    for s = 1 : nScoringRules
        [pointsScore(:, 1, s), ~] = find(pref(:,:,:,s) == 1);
        [pointsScore(:, 2, s), ~] = find(pref(:,:,:,s) == 2);
        [pointsScore(:, 3, s), ~] = find(pref(:,:,:,s) == 3);
        [pointsScore(:, 4, s), ~] = find(pref(:,:,:,s) == 4);
    end
    
    pointsScore = permute(pointsScore, [2 1 3]);
    pointsScore = reshape(pointsScore, nOptions, nRankings, nCitizens, nScoringRules);

    generalScoreWinner = zeros(nRankings, nScoringRules);
    generalScoreWin1 = zeros(nRankings, nScoringRules);
    generalScoreWin2 = zeros(nRankings, nScoringRules);
    generalScoreWin3 = zeros(nRankings, nScoringRules);
    generalScoreWin4 = zeros(nRankings, nScoringRules);

    tieGeneralScore = zeros(nRankings, nScoringRules);

    nScoringResolution = 101;
    sLower = -5;
    s = linspace(sLower, 5, nScoringResolution);


    generalScoreAll = zeros(nOptions, nRankings, nCitizens, nScoringResolution);

    for scoreIndex = 1:nScoringResolution 

        s1 = (1/3)^(exp(s(scoreIndex))/exp(0));
        s2 = (2/3)^(exp(s(scoreIndex))/exp(0));

        weights = [1, s2, s1, 0];
        generalScore =   weights(1) * (pointsScore(:,:,:,scoreIndex) == 1) ...
                       + weights(2) * (pointsScore(:,:,:,scoreIndex) == 2) ...
                       + weights(3) * (pointsScore(:,:,:,scoreIndex) == 3) ...
                       + weights(4) * (pointsScore(:,:,:,scoreIndex) == 4) ;
                   
        generalScoreAll(:,:,:,scoreIndex) = generalScore; 

    end

  
    
    
  
    % Drop option ranked last
    dropOption = scoreRanks == 4; 
    dropOption = reshape(dropOption, nOptions, nRankings, 1, nScoringRules);
    dropOption = repmat(dropOption, 1, 1, 5, 1);

    % New preference profile, in which the preference for the dropped option is
    % set to 5: 
    prefKept = pref.*(1 - dropOption) + (1+nOptions) * dropOption; 

    % Relabel preference ranks to 1 and 2, such that the unavailable option
    % receives preference 3 for all Choosers. 
    for i = 1 : nRankings
        for s = 1 : nScoringRules
            for j = 1 : 5 
                [~,prefKept(:,i,j,s)]=ismember(prefKept(:,i,j,s),sort(prefKept(:,i,j,s),'ascend'));
            end
        end
    end
  
    % Select remainig option
    
    reshape(prefKept, nOptions, nCitizens, nRankings, nScoringRules);
    
    
    votesScRunoff1 = sum(prefKept(1,:) == 1); 
    votesScRunoff2 = sum(prefKept(1,:) == 2); 
    votesScRunoff3 = sum(prefKept(1,:) == 3); 
    votesScRunoff4 = sum(prefKept(1,:) == 4); 
    
    
    
    
    
    
    
end



%% Runoffs handcoded
   
% Plurality runoff
pluralityRunoffWin1 = [1 1 1 1 0 0]';              
pluralityRunoffWin2 = [0 0 0 0 0 0]';              
pluralityRunoffWin3 = [0 0 0 0 0 0]';              
pluralityRunoffWin4 = [0 0 0 0 1 1]';              
              
% Antiplurality runoff

% In all six profiles, the antiplurality runoff winner coincides with the 
% antiplurality winner (assuming that for profiles 5 and 6 ties are
% resolved in favor of the option with the better rank-distribution in the
% first round. 

% But I get the same outcome if I instead drop the two options that tie for
% the lowest score
              
antipluralityRunoffWin1 = [1 1 0 0 0 0]';              
antipluralityRunoffWin2 = [1 1 1 1 1 1]';              
antipluralityRunoffWin3 = [0 0 0 0 0 0]';              
antipluralityRunoffWin4 = [0 0 0 0 0 0]';              
              
              
% Borda runoff

% Drop both options that tie for the lowest score in profiles 5 and 6

bordaRunoffWin1 = [1 1 0 0 1 1]';              
bordaRunoffWin2 = [1 1 1 1 0 0]';              
bordaRunoffWin3 = [0 0 0 0 0 0]';              
bordaRunoffWin4 = [0 0 0 0 0 0]';              

% Malevolent plurality runoff
badPluralityRunoffWin1 = [0 0 0 0 1 1]';              
badPluralityRunoffWin2 = [0 0 0 0 0 0]';              
badPluralityRunoffWin3 = [0 0 0 0 0 0]';              
badPluralityRunoffWin4 = [1 1 1 1 0 0]';              

% Malevolent antiplurality runoff
badAntipluralityRunoffWin1 = [0 0 0 0 0 0]';              
badAntipluralityRunoffWin2 = [0 0 0 0 0 1]';              
badAntipluralityRunoffWin3 = [0 0 0 1 1 0]';              
badAntipluralityRunoffWin4 = [1 1 1 0 0 0]';              

% Malevolent Borda runoff

badBordaRunoffWin1 = [0 0 0 0 0 0]';              
badBordaRunoffWin2 = [0 0 0 0 0 0]';              
badBordaRunoffWin3 = [0 0 0 0 0 0]';              
badBordaRunoffWin4 = [1 1 1 1 1 1]';              



%% Binary relations

unanimityWin1 = [1 1 1 1 1 1]';              
unanimityWin2 = [1 1 1 1 1 1]';              
unanimityWin3 = [1 1 1 1 1 1]';              
unanimityWin4 = [1 1 1 1 1 1]';              

supermajorityWin1 = [1 1 1 1 1 1]';              
supermajorityWin2 = [1 1 1 1 1 1]';              
supermajorityWin3 = [1 1 1 1 1 1]';              
supermajorityWin4 = [1 1 1 1 1 1]';              

indifferenceWin1 = [1 1 1 1 1 1]';              
indifferenceWin2 = [1 1 1 1 1 1]';              
indifferenceWin3 = [1 1 1 1 1 1]';              
indifferenceWin4 = [1 1 1 1 1 1]';              

% Malevolent Condorcet

badCondorcetWin1 = [0 0 0 0 1 1]';              
badCondorcetWin2 = [0 0 0 0 1 1]';              
badCondorcetWin3 = [0 0 0 0 1 1]';              
badCondorcetWin4 = [1 1 1 1 1 1]';              


%% Output data in file for stata use

s = 1;
scoring0plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 41;
scoring40plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 51;
scoring50plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 61;
scoring60plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 67;
scoring66plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 69;
scoring68plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 72;
scoring71plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 74;
scoring73plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 78;
scoring77plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 91;
scoring90plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];
s = 101;
scoring100plot = [generalScoreWin1(:,s), generalScoreWin2(:,s), generalScoreWin3(:,s), generalScoreWin4(:,s)];



s = 1;
BadScoring0plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 41;
BadScoring40plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 51;
BadScoring50plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 61;
BadScoring60plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 67;
BadScoring66plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 69;
BadScoring68plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 72;
BadScoring71plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 74;
BadScoring73plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 78;
BadScoring77plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 91;
BadScoring90plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];
s = 101;
BadScoring100plot = [generalBadScoreWin1(:,s), generalBadScoreWin2(:,s), generalBadScoreWin3(:,s), generalBadScoreWin4(:,s)];



%Define the knife-edge rules as the union of the non-knife-edge rules
scoring50plot = max(scoring40plot, scoring60plot);
scoring67plot = max(scoring66plot, scoring71plot);
scoring75plot = max(scoring73plot, scoring77plot);

BadScoring50plot = max(BadScoring40plot, BadScoring60plot);
BadScoring67plot = max(BadScoring66plot, BadScoring71plot);
BadScoring75plot = max(BadScoring73plot, BadScoring77plot);

pluralityRunoffPlot = [pluralityRunoffWin1, pluralityRunoffWin2, pluralityRunoffWin3, pluralityRunoffWin4];
bordaRunoffPlot = [bordaRunoffWin1, bordaRunoffWin2, bordaRunoffWin3, bordaRunoffWin4];
antipluralityRunoffPlot = [antipluralityRunoffWin1, antipluralityRunoffWin2, antipluralityRunoffWin3, antipluralityRunoffWin4];

indifferencePlot = [indifferenceWin1, indifferenceWin2, indifferenceWin3, indifferenceWin4];
supermajorityPlot = [supermajorityWin1, supermajorityWin2, supermajorityWin3, supermajorityWin4];
unanimityPlot = [unanimityWin1, unanimityWin2, unanimityWin3, unanimityWin4];

condorcetPlot = [condorcetWin1, condorcetWin2, condorcetWin3, condorcetWin4];
badCondorcetPlot = [badCondorcetWin1, badCondorcetWin2, badCondorcetWin3, badCondorcetWin4];

badPluralityRunoffPlot = [badPluralityRunoffWin1, badPluralityRunoffWin2, badPluralityRunoffWin3, badPluralityRunoffWin4];
badBordaRunoffPlot = [badBordaRunoffWin1, badBordaRunoffWin2, badBordaRunoffWin3, badBordaRunoffWin4];
badAntipluralityRunoffPlot = [badAntipluralityRunoffWin1, badAntipluralityRunoffWin2, badAntipluralityRunoffWin3, badAntipluralityRunoffWin4];

badSupermajorityPlot = supermajorityPlot;
badUnanimityPlot = unanimityPlot;





%% Making rules like in three-option case

if 0 

ruleResults = cat(3, ...
			scoring0plot, ...
			scoring40plot, ...
			scoring50plot, ...
			scoring60plot, ...
			scoring66plot, ...
			scoring67plot, ...
			scoring71plot, ...
			scoring75plot, ...
			scoring77plot, ...
			scoring90plot, ...
			scoring100plot, ...
            pluralityRunoffPlot, ...
            bordaRunoffPlot, ...
            antipluralityRunoffPlot, ...
            condorcetPlot, ...
            supermajorityPlot, ...
            unanimityPlot, ...
            indifferencePlot);
            
[~, ~, nRules] = size(ruleResults);

ruleNames = [ ...
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...
"runoff"; ...
"runoff"; ...
"runoff"; ...
"condorcet"; ...
"supermajority"; ...
"unanimity"; ...
"indifference"]; 


   
rulePara = ...
           [01, -1,  -1 ; ...
            02, 40,  40 ; ...
	        03, 50,  50 ; ...
            04, 60,  60 ; ...
	        05, 66,  66 ; ...
            06, 68,  68 ; ...
	        07, 71,  71 ; ...
            08, 74,  74 ; ...
	        09, 77,  77 ; ...
            10, 90,  90 ; ...
	        11, 100, 100; ...
	        12, 0, 0; ...
	        13, 50, 50; ...
	        14, 100, 100; ...
            15, 0  , 0  ; ...
            16, 0  , 0  ; ...
            17, 0  , 0  ; ...
            18, 0  , 0  ];      

end

%% Making rules that correspond to three-option classification

scoring50to67plot = max(scoring66plot, scoring67plot);
scoring67to75plot = max(scoring68plot, scoring71plot);
scoring67to75plot = max(scoring67to75plot, scoring73plot);
scoring75to100plot = max(scoring77plot, scoring90plot);

BadScoring50to67plot = max(BadScoring66plot, BadScoring67plot);
BadScoring67to75plot = max(BadScoring68plot, BadScoring71plot);
BadScoring67to75plot = max(BadScoring67to75plot, BadScoring73plot);
BadScoring75to100plot = max(BadScoring77plot, BadScoring90plot);

ruleResults = cat(3, ...
			scoring0plot, ...
			scoring40plot, ...
			scoring40plot, ...
			scoring40plot, ...
			scoring50plot, ...
			scoring60plot, ...
			scoring60plot, ...
            scoring50to67plot, ...
   			scoring67plot, ...
			scoring67to75plot, ...
			scoring75plot, ...
			scoring75to100plot, ...
			scoring90plot, ...
			scoring90plot, ...
			scoring100plot, ...
            pluralityRunoffPlot, ...
            bordaRunoffPlot, ...
            antipluralityRunoffPlot, ...
            condorcetPlot, ...
            supermajorityPlot, ...
            unanimityPlot, ...
            indifferencePlot, ...
            BadScoring0plot, ...
			BadScoring40plot, ...
			BadScoring40plot, ...
			BadScoring40plot, ...
			BadScoring50plot, ...
			BadScoring60plot, ...
			BadScoring60plot, ...
            BadScoring50to67plot, ...
   			BadScoring67plot, ...
			BadScoring67to75plot, ...
			BadScoring75plot, ...
			BadScoring75to100plot, ...
			BadScoring90plot, ...
			BadScoring90plot, ...
			BadScoring100plot, ...
            badPluralityRunoffPlot, ...
            badBordaRunoffPlot, ...
            badAntipluralityRunoffPlot, ...
            badCondorcetPlot, ...
            badSupermajorityPlot, ...
            badUnanimityPlot);
            
[~, ~, nRules] = size(ruleResults);

ruleNames = [ 
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"scoring"; ...      
"runoff"; ...
"runoff"; ...
"runoff"; ...
"condorcet"; ...
"supermajority"; ...
"unanimity"; ...
"indifference";...
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring"; ...      
"malevolentScoring";
"badrunoff"; ...
"badrunoff"; ...
"badrunoff"; ...
"badcondorcet"; ...
"badsupermajority"; ...
"badunanimity"]; 


   
rulePara = ...
           [01, 0,   0; ...
            02, 0,   50; ...
	        03, 0,   50 ; ...
            04, 0,   50 ; ...
	        05, 50,  50 ; ...
            06, 50,  65 ; ...
	        07, 50,  65 ; ...
            08, 50,  67 ; ...
	        09, 67,  67 ; ...
            10, 67,  75 ; ...
	        11, 75, 75; ...
	        12, 75, 100; ...
	        13, 79, 100; ...
	        14, 79, 100; ...
	        15, 100, 100; ...
	        16, 0, 0; ...
	        17, 50, 50; ...
	        18, 100, 100; ...
            19, 0  , 0  ; ...
            20, 0  , 0  ; ...
            21, 0  , 0  ; ...
            22, 0  , 0  ; ...
            23, 0,   0; ...
            24, 0,   50; ...
	        25, 0,   50 ; ...
            26, 0,   50 ; ...
	        27, 50,  50 ; ...
            28, 50,  65 ; ...
	        29, 50,  65 ; ...
            30, 50,  67 ; ...
	        31, 67,  67 ; ...
            32, 67,  75 ; ...
	        33, 75, 75; ...
	        34, 75, 100; ...
	        35, 79, 100; ...
	        36, 79, 100; ...
	        37, 100, 100; ...
            38, 0, 0; ...
            39, 50, 50; ...
            40, 100, 100; ...
            41, 0, 0; ...
            42, 0, 0; ...
            43, 0, 0];    

        
ruleResults = permute(ruleResults, [2 1 3]);     

rulePara = repmat(rulePara, 1, 1, nRankings);
rulePara = permute(rulePara, [2 3 1]);
        
ruleNames = repmat(ruleNames, 1, 1, nRankings);
ruleNames = permute(ruleNames, [2 3 1]);
        
  
ruleData = cat(1, ruleResults, ruleNames, rulePara); 

prefExport = [pref(:,:,1)', pref(:,:,2)', pref(:,:,3)', pref(:,:,4)', pref(:,:,5)'];


profileIndex = 1:6;
profileIndex = profileIndex';

ruleDataLong = [profileIndex, ones(nRankings, 1), ruleData(:,:,1)', prefExport];
for r = 2 : nRules 
    ruleDataLong = cat(1, ruleDataLong, [profileIndex, r*ones(nRankings, 1), ruleData(:,:,r)', prefExport]);
end



rowNames = 1:nRankings;
colNames = {'profileIndex', 'ruleIndex', ...
            'optionA', 'optionB', 'optionC', 'optionD', ...
            'ruleName', 'ruleIndex2',  'scLow', 'scHigh', ...
            'pref1st_1', 'pref2nd_1', 'pref3rd_1', 'pref4th_1', ...
            'pref1st_2', 'pref2nd_2', 'pref3rd_2', 'pref4th_2', ...
            'pref1st_3', 'pref2nd_3', 'pref3rd_3', 'pref4th_3', ...
            'pref1st_4', 'pref2nd_4', 'pref3rd_4', 'pref4th_4', ...
            'pref1st_5', 'pref2nd_5', 'pref3rd_5', 'pref4th_5'};
        
table = array2table(ruleDataLong,'VariableNames',colNames);
writetable(table, 'data/rulePredictions4opt.csv')





