function [qnRefactored, nrefactorings] = softwareRefactorSCMerge(qn, alternatives, constraints, rates)
	% SOFTWAREREFACTORSCMERGE
	%
	% This function replaces mergeable components with merged substitutes that
	% increase the score.
	%
	% INPUT
	% qn: queuing network
	% alternatives: matrix of cells in which each cells contains a matrix. Each
	% row of the matrix contains alternative rates for each class.
	% Columns are the classes.
	%
	% OUTPUT
	% qnRefactored: new qn after applying refactorings
	% nrefactorings: number of refactorings that have been performed
	% merged: boolean triangular matrix in which true elements are the ones
	%			 corresponding to software components that have been merged
	
	myqn = qn;
	qnRefactored = qn;
	myalternatives = alternatives;
	nrefactorings = 0;
	
	for ii=1:numel(rates)
 		myqn.rates(ii,:) = myqn.rates(ii,:)*rates(ii);
	end
	
	qnv = QNValue(myqn);
	qnv = qnv.evaluate();
	
	ii=1;
	while ii<=myqn.M-1
		jj=ii+1;
		while jj<=myqn.M		
			if strcmp(qn.sched(ii),'inf') || strcmp(qn.sched(jj),'inf') || ...
					isempty(alternatives{ii,jj})
				
				jj = jj+1;
				continue;
			end
		
			score = evaluateSCMerge(qnv, ii, jj, myalternatives{ii,jj}*rates(ii), constraints);
			maxscore = max(score);
		
			if maxscore>eps
				best = find(score == maxscore);
				best = best(1);
				disp(['Merging QN' num2str(ii) '+QN' num2str(jj) ...
					' old1=<' num2str(qnRefactored.rates(ii,:)) '> ' ...
					'old2=<' num2str(qnRefactored.rates(jj,:)) '> new=<' ...
					num2str(myalternatives{ii,jj}(best,:)) '>']);
				myqn = scMerge(myqn, ii, jj, myalternatives{ii,jj}(best,:)*rates(ii));
				qnRefactored = scMerge(qnRefactored, ii, jj, myalternatives{ii,jj}(best,:));
				nrefactorings = nrefactorings + 1;
				myalternatives(jj,:) = [];
				myalternatives(:,jj) = [];
				qnv = QNValue(myqn);
				qnv = qnv.evaluate();
			end
			
			jj = jj+1;
		end

		ii = ii+1;
	end

end