function [Population] = Migration(Population,AMMIG,NPl)

%% Emigration scheme - round robin
% idx = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of migrants
% MigrantsTo = Population(:,idx);
% labTo = mod(labindex, numlabs) + 1; % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1; % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% Population(:,idx) = MigrantsFrom;

%% Elitist scheme - round robin
% [~, idx] = sort(Population(1,:));         % sort for best choice of migrants
% MigrantsTo = Population(:,idx(1:AMMIG));
% labTo = mod(labindex, numlabs) + 1; % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1; % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% Population(:,idx(NPl-AMMIG+1:NPl)) = MigrantsFrom;

%% Elitist scheme with tournament selection of migrants - round robin
% idx = zeros(1,AMMIG);                            % indices of chosen migrants
% idx1 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 1
% idx2 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 2
% [~, idxS] = sort(Population(1,:));               % sort for worst choice of migrants
% 
% % Tournament selection
% for i = 1 : AMMIG
%    if ( Population(1,idx1(i)) >=  Population(1,idx2(i)) )
%        idx(i) = idx2(i);   
%    else
%        idx(i) = idx1(i);
%    end    
% end
% 
% MigrantsTo = Population(:,idx(1:AMMIG));
% labTo = mod(labindex, numlabs) + 1;         % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1;   % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% Population(:,idxS(NPl-AMMIG+1:NPl)) = MigrantsFrom;

%% Emigration scheme - random
% idx = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of migrants
% MigrantsTo = Population(:,idx);
% 
% % it generates random vektor that determines lab for migration for each one
% % and send it to all labs
% 
% if (labindex == 1)
%     ord = 1 : numlabs;
%     for i = 1 : numlabs
%         rnd = rand;
%         poc = 0;
%         ind = 0;
%         while (rnd > poc)
%             ind = ind + 1;
%             poc = poc + (1/(numlabs-i+1));
%         end
%         vek(i) = ord(ind);
%         ord(ind) = inf;
%         ord(ind) = ord(numlabs-i+1);
%     end
%     vek = labBroadcast(1,vek);
% else
%     vek = labBroadcast(1);    
% end
% 
% labTo = vek(labindex);
% 
% labBarrier
% 
% if (vek(labindex) ~= labindex)
%     labSend(MigrantsTo,labTo);
%     MigrantsFrom = labReceive;
% else
%     MigrantsFrom = MigrantsTo;
% end
% Population(:,idx) = MigrantsFrom;


%% Elitist scheme - random
% [~, idx] = sort(Population(1,:));         % sort for best choice of migrants
% MigrantsTo = Population(:,idx(1:AMMIG));
% 
% % it generates random vektor that determines lab for migration for each one
% % and send it to all labs
% 
% if (labindex == 1)
%     ord = 1 : numlabs;
%     for i = 1 : numlabs
%         rnd = rand;
%         poc = 0;
%         ind = 0;
%         while (rnd > poc)
%             ind = ind + 1;
%             poc = poc + (1/(numlabs-i+1));
%         end
%         vek(i) = ord(ind);
%         ord(ind) = inf;
%         ord(ind) = ord(numlabs-i+1);
%     end
%     vek = labBroadcast(1,vek);
% else
%     vek = labBroadcast(1);    
% end
% 
% labTo = vek(labindex);
% 
% labBarrier
% 
% if (vek(labindex) ~= labindex)
%     labSend(MigrantsTo,labTo);
%     MigrantsFrom = labReceive;
% else
%     MigrantsFrom = MigrantsTo;
% end
% Population(:,idx(NPl-AMMIG+1:NPl)) = MigrantsFrom;

%% Elitist scheme with tournament selection - random
% idx = zeros(1,AMMIG);                            % indices of chosen migrants
% idx1 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 1
% idx2 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 2
% [~, idxS] = sort(Population(1,:));               % sort for worst choice of migrants
% 
% 
% % Tournament selection
% for i = 1 : AMMIG
%    if ( Population(1,idx1(i)) >=  Population(1,idx2(i)) )
%        idx(i) = idx2(i);   
%    else
%        idx(i) = idx1(i);
%    end    
% end
% 
% MigrantsTo = Population(:,idx(1:AMMIG));
% 
% % it generates random vektor that determines lab for migration for each one
% % and send it to all labs
% 
% if (labindex == 1)
%     ord = 1 : numlabs;
%     for i = 1 : numlabs
%         rnd = rand;
%         poc = 0;
%         ind = 0;
%         while (rnd > poc)
%             ind = ind + 1;
%             poc = poc + (1/(numlabs-i+1));
%         end
%         vek(i) = ord(ind);
%         ord(ind) = inf;
%         ord(ind) = ord(numlabs-i+1);
%     end
%     vek = labBroadcast(1,vek);
% else
%     vek = labBroadcast(1);    
% end
% 
% labTo = vek(labindex);
% 
% labBarrier
% 
% if (vek(labindex) ~= labindex)
%     labSend(MigrantsTo,labTo);
%     MigrantsFrom = labReceive;
% else
%     MigrantsFrom = MigrantsTo;
% end
% 
% Population(:,idxS(NPl-AMMIG+1:NPl)) = MigrantsFrom;

% dalsi muze byt nahrazeni jedinci treba u elitist modelu budou jen ti
% kteri budou mit lepsi fitness nez ti co meli byt nahrazeni


%% Emigration scheme - round robin, for repleace choose among MigrantsTo and MigrantsFrom
% idx = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of migrants
% MigrantsTo = Population(:,idx);
% 
% labTo = mod(labindex, numlabs) + 1; % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1; % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% 
% % merge migrantsfrom with migrantsto and choose AMMIG beest of them
% BestOf = [MigrantsFrom Population(:,idx)];
% [~, idxB] = sort(BestOf(1,:));
% Population(:,idx) = BestOf(:,idxB(1:AMMIG));


%% Elitist scheme - round robin, for repleace choose among MigrantsTo and MigrantsFrom
% [~, idx] = sort(Population(1,:));         % sort for best choice of migrants
% MigrantsTo = Population(:,idx(1:AMMIG));
% labTo = mod(labindex, numlabs) + 1; % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1; % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% 
% BestOf = [MigrantsFrom Population(:,idx(NPl-AMMIG+1:NPl))];
% [~, idxB] = sort(BestOf(1,:));
% 
% Population(:,idx(NPl-AMMIG+1:NPl)) = BestOf(:,idxB(1:AMMIG));

%% Elitist scheme with tournament selection of migrants - round robin, best replace
% idx = zeros(1,AMMIG);                            % indices of chosen migrants
% idx1 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 1
% idx2 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 2
% [~, idxS] = sort(Population(1,:));               % sort for worst choice of migrants
% 
% % Tournament selection
% for i = 1 : AMMIG
%    if ( Population(1,idx1(i)) >=  Population(1,idx2(i)) )
%        idx(i) = idx2(i);   
%    else
%        idx(i) = idx1(i);
%    end    
% end
% 
% MigrantsTo = Population(:,idx(1:AMMIG));
% labTo = mod(labindex, numlabs) + 1;         % one lab to the right
% labFrom = mod(labindex - 2, numlabs) + 1;   % one lab to the left
% 
% labBarrier
% 
% MigrantsFrom = labSendReceive(labTo, labFrom, MigrantsTo);
% 
% BestOf = [MigrantsFrom Population(:,idxS(NPl-AMMIG+1:NPl))];
% [~, idxB] = sort(BestOf(1,:));
% 
% Population(:,idxS(NPl-AMMIG+1:NPl)) = BestOf(:,idxB(1:AMMIG));
% 
%% Emigration scheme - random migration and best replace scheme
% idx = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of migrants
% MigrantsTo = Population(:,idx);
% 
% % it generates random vektor that determines lab for migration for each one
% % and send it to all labs
% 
% if (labindex == 1)
%     ord = 1 : numlabs;
%     for i = 1 : numlabs
%         rnd = rand;
%         poc = 0;
%         ind = 0;
%         while (rnd > poc)
%             ind = ind + 1;
%             poc = poc + (1/(numlabs-i+1));
%         end
%         vek(i) = ord(ind);
%         ord(ind) = inf;
%         ord(ind) = ord(numlabs-i+1);
%     end
%     vek = labBroadcast(1,vek);
% else
%     vek = labBroadcast(1);    
% end
% 
% labTo = vek(labindex);
% 
% labBarrier
% 
% if (vek(labindex) ~= labindex)
%     labSend(MigrantsTo,labTo);
%     MigrantsFrom = labReceive;
% else
%     MigrantsFrom = MigrantsTo;
% end
% 
% % merge migrantsfrom with migrantsto and choose AMMIG beest of them
% BestOf = [MigrantsFrom Population(:,idx)];
% [~, idxB] = sort(BestOf(1,:));
% Population(:,idx) = BestOf(:,idxB(1:AMMIG));

%% Elitist scheme - random migration and best replace strategy
% [~, idx] = sort(Population(1,:));         % sort for best choice of migrants
% MigrantsTo = Population(:,idx(1:AMMIG));
% 
% % it generates random vektor that determines lab for migration for each one
% % and send it to all labs
% 
% if (labindex == 1)
%     ord = 1 : numlabs;
%     for i = 1 : numlabs
%         rnd = rand;
%         poc = 0;
%         ind = 0;
%         while (rnd > poc)
%             ind = ind + 1;
%             poc = poc + (1/(numlabs-i+1));
%         end
%         vek(i) = ord(ind);
%         ord(ind) = inf;
%         ord(ind) = ord(numlabs-i+1);
%     end
%     vek = labBroadcast(1,vek);
% else
%     vek = labBroadcast(1);    
% end
% 
% labTo = vek(labindex);
% 
% labBarrier
% 
% if (vek(labindex) ~= labindex)
%     labSend(MigrantsTo,labTo);
%     MigrantsFrom = labReceive;
% else
%     MigrantsFrom = MigrantsTo;
% end
% 
% BestOf = [MigrantsFrom Population(:,idx(NPl-AMMIG+1:NPl))];
% [~, idxB] = sort(BestOf(1,:));
% 
% Population(:,idx(NPl-AMMIG+1:NPl)) = BestOf(:,idxB(1:AMMIG));


%% Elitist scheme with tournament selection - random migration, best replace
idx = zeros(1,AMMIG);                            % indices of chosen migrants
idx1 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 1
idx2 = round(1+(NPl-1).*rand(1,AMMIG));          % random choice of possible migrants 2
[~, idxS] = sort(Population(1,:));               % sort for worst choice of migrants


% Tournament selection
for i = 1 : AMMIG
   if ( Population(1,idx1(i)) >=  Population(1,idx2(i)) )
       idx(i) = idx2(i);   
   else
       idx(i) = idx1(i);
   end    
end

MigrantsTo = Population(:,idx(1:AMMIG));

% it generates random vektor that determines lab for migration for each one
% and send it to all labs

if (labindex == 1)
    ord = 1 : numlabs;
    for i = 1 : numlabs
        rnd = rand;
        poc = 0;
        ind = 0;
        while (rnd > poc)
            ind = ind + 1;
            poc = poc + (1/(numlabs-i+1));
        end
        vek(i) = ord(ind);
        ord(ind) = inf;
        ord(ind) = ord(numlabs-i+1);
    end
    vek = labBroadcast(1,vek);
else
    vek = labBroadcast(1);    
end

labTo = vek(labindex);

labBarrier

if (vek(labindex) ~= labindex)
    labSend(MigrantsTo,labTo);
    MigrantsFrom = labReceive;
else
    MigrantsFrom = MigrantsTo;
end

BestOf = [MigrantsFrom Population(:,idxS(NPl-AMMIG+1:NPl))];
[~, idxB] = sort(BestOf(1,:));

Population(:,idxS(NPl-AMMIG+1:NPl)) = BestOf(:,idxB(1:AMMIG));



