function [outmat]=optimizerepandfaktorausschluss(reihe,faktorausschlussmat,berichtstatus,target)

%   optimizerepandfaktorausschluss

%   This software is protected by german copyright and international treaties.             
%   Copyright 2004 Markus Junghöfer & Peter Peyk. All Rights Reserved.                     
%                                                                                          
%   THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE        
%   NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,    
%   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE    
%   OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
%   TRADEMARKS OR OTHER RIGHTS. COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT,       
%   INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE      
%   OR DOCUMENTATION.                                                                      

erfolg = 0;erfolgloszaehler=0;erfolgsmat=[];gesamterfolgloszaehler=0;
anzahlwiederholungen = 1;indssort=[];
if anzahlwiederholungen == -1; uiwait(errordlg('Optimierung sinnlos bei unbeschränkter Wiederholung!','Achtung:'));
outmat=[];return;end;neuziehenzaehler=1;sternzaehler=1;
if nargin<4; berichtstatus=0;end
if nargin<3;ausschlussmat = [];end
outmat=zeros(1,length(reihe));


while sum(erfolgsmat)< length(faktorausschlussmat)
   
    %target auswählen
    %------------------
    
    %erster Durchgange inputtarget
    if gesamterfolgloszaehler==0
        target = target;
    %dann:
    else
        moeglichetargets=shuffle(find(erfolgsmat==0));
        target=moeglichetargets(1);
    end
    
    %indices des targets
	%-----------------
	inds=find(reihe==target);
	indsini=inds;
   
    
	while erfolg == 0
            
		inds=find(reihe==target);  
        
		%problempos finden
		%---------------------
		problemstellenvec=[];
		problemstellenzaehler=1;
		resourcestellenvec=[];
		resourcestellenzaehler=1;
		check=[];
		diffs = diff(inds);
		for i=1:length(inds)
            diffmat=zeros(anzahlwiederholungen+(anzahlwiederholungen-2),1);
            groessediffmat = anzahlwiederholungen+(anzahlwiederholungen-2);
            if anzahlwiederholungen == 1
                if i<=length(diffs)
                    diffmat=diffs(i);
                else
                    diffmat=0;
                end
            end
            for j=1:anzahlwiederholungen-1
                %upper
                if i+j-1<length(diffs)
                    if groessediffmat/2+j<=length(diffmat)
                        diffmat(groessediffmat/2+j)=diffs(i+j-1);
                    end
                end
                %lower
                if i-j>0
                    if groessediffmat/2+1-j>0
                        diffmat(groessediffmat/2+1-j)=diffs(i-j*1);
                    end
                end  
            end
            evalstring='diffmat==1';
            for t=1:anzahlwiederholungen-1
                evalstring=['diff(find(',evalstring,'))==1'];
            end
            evalstring=['if ~isempty(find(',evalstring,'));',...
                    'problemstellenvec(problemstellenzaehler)=i;problemstellenzaehler=problemstellenzaehler+1;end'];
            if sum(1==diffmat)>=anzahlwiederholungen-1
                 warning off
                 eval(evalstring);
                 warning on
            end
		end
        
		%resourcenpos finden
		%--------------------
		resourcenstellenvec=[];
		indshelp=inds;
		if inds(1)~=1;indshelp=[1,indshelp];end
		if inds(end)~=length(outmat);indshelp=[indshelp,length(outmat)];end
		diffinds=diff(indshelp);
		resourcenzaehler=1;
		naechsteserie=1;
		resourcenstellen=find(diffinds>3);
        sonderresourcen=find(diffinds==3);
        for q=1:length(sonderresourcen)
            sonderresourcenstellenvec(q)=indshelp(sonderresourcen(q));
        end
		for i=1:length(resourcenstellen)
            naechsteserie = 1;
            serienabschnitte = 0;
            while naechsteserie == 1
                naechsteserie = 0;
                serienzaehler = 1;
                while serienzaehler<=anzahlwiederholungen & serienzaehler<diffinds(resourcenstellen(i))-2
                    resourcenstellenvec(resourcenzaehler)=indshelp(resourcenstellen(i))+1+serienzaehler+serienabschnitte;
                    resourcenzaehler=resourcenzaehler+1;
                    serienzaehler = serienzaehler + 1; 
                end
                if indshelp(resourcenstellen(i))+1+serienabschnitte + serienzaehler + 1 < indshelp(resourcenstellen(i)+1)-1
                    naechsteserie = 1;
                    serienabschnitte=serienabschnitte + serienzaehler;
                end
            end
		end
        
        %ausschlussmat berücksichtigen
        %---------------------------
        if ~isempty(faktorausschlussmat{target})
            denyresourcenstellenvec=zeros(1,length(resourcenstellen));
            for y=1:length(faktorausschlussmat{target})
                for u=1:length(resourcenstellenvec)
                    if reihe(resourcenstellenvec(u)-1)==faktorausschlussmat{target}(y) | reihe(resourcenstellenvec(u)+1)==faktorausschlussmat{target}(y) 
                        denyresourcenstellenvec(u)=1;
                    end
                end
            end
            resourcenstellenvec(find(denyresourcenstellenvec==1))=[];
        end
        
		%abbruch
		%-------
		if ~isempty(problemstellenvec)
            if isempty(resourcenstellenvec)
                if berichtstatus == 1
                    inds
                    problemstellenvec
                    resourcenstellen
                    uiwait(errordlg('Verteilung der <mergemat> unter geforderten Wiederholungsbedingungen schwierig in <optimizerepandfaktorausschluss.m>!','Achtung:'));
                end
                inds=[];
                return;
            end
        else
            outmat=reihe;
            return
        end
        
		if berichtstatus == 1
			length(problemstellenvec)
			indini=inds
		end       
        
        %resourcenstellenvec mischen
        %------------------
        resourcenstellenvec=shuffle(resourcenstellenvec);
        problemstellenvec=shuffle(problemstellenvec);
        
		%problempos auf resourcenpos verteilen
		%------------------------------------
		anzahloptimierungsdurchgaenge=1;
		if berichtstatus == 1
            disp([num2str(length(problemstellenvec)),' verbleibende Problemstellen...']);
		end
		problemstellenvectmp=problemstellenvec;
        tryagain = 0;
        trysonderresourcenstatus = 0;
        
        %Optimierung
		%-----------------
        
		while length(problemstellenvectmp)>0
			
            
            indstmp=inds;
            anzahlresourcenstellen = length(resourcenstellenvec);
            anzahlproblemstellen = length(problemstellenvec);
        
			%Normale Resourcen
            %---------------------
            if anzahlresourcenstellen~=0
                if tryagain==0
                    anzahlresourcenstellen = length(resourcenstellenvec);
                    anzahlproblemstellen = length(problemstellenvec);
                    tryagainzaehler=1;
                    indstmp(problemstellenvec(tryagainzaehler))=resourcenstellenvec(tryagainzaehler);
                elseif tryagain==1
                    tryagainzaehler=tryagainzaehler+1;
                    if floor(tryagainzaehler/anzahlresourcenstellen)+1>anzahlproblemstellen
                        trysonderresourcenstatus = 1;
                    end
                    if trysonderresourcenstatus ==0
                        indstmp(problemstellenvec(floor(tryagainzaehler/anzahlresourcenstellen)+1))=resourcenstellenvec(mod(tryagainzaehler,anzahlresourcenstellen)+1)
                    end 
                end
            else
               trysonderresourcenstatus = 1;
            end
           
            %Sonderresourcen
            %_---------------
            if trysonderresourcenstatus == 1
                if berichtstatus == 1
                    fprintf('Sonderresourcen...');
                end
                for sonderresourcenzaehler=1:length(sonderresourcen)-1
                    indstmp(sonderresourcen(sonderresourcenzaehler)+1:end)=indshelp(sonderresourcen(sonderresourcenzaehler)+1:end)-1;
                end
            end
            
            indssort=sort(indstmp);
            diffs = diff(indssort);
            
			%problemposveränderung testen
			%----------------------------
			problemstellenvectmp=[];
			problemstellenzaehlertmp=1;
			for i=1:length(inds)
                diffmat=zeros(anzahlwiederholungen+(anzahlwiederholungen-2),1);
                groessediffmat = anzahlwiederholungen+(anzahlwiederholungen-2);
                if anzahlwiederholungen == 1
                    if i<=length(diffs)
                        diffmat=diffs(i);
                    else
                        diffmat=0;
                    end
                end
                for j=1:anzahlwiederholungen-1
                    %upper
                    if i+j-1<length(diffs)
                        if groessediffmat/2+j<=length(diffmat)
                            diffmat(groessediffmat/2+j)=diffs(i+j-1);
                        end
                    end
                    %lower
                    if i-j>0
                        if groessediffmat/2+1-j>0
                            diffmat(groessediffmat/2+1-j)=diffs(i-j*1);
                        end
                    end  
                end
                evalstring='diffmat==1';
                for t=1:anzahlwiederholungen-1
                    evalstring=['diff(find(',evalstring,'))==1'];
                end
                evalstring=['if ~isempty(find(',evalstring,'));',...
                'problemstellenvectmp(problemstellenzaehlertmp)=i;problemstellenzaehlertmp=problemstellenzaehlertmp+1;end'];
              if sum(1==diffmat)>=anzahlwiederholungen-1
                     warning off
                     eval(evalstring);
                     warning on
              end
			end
            
			%Progress
			%-------------------
			if length(problemstellenvectmp)<length(problemstellenvec) | trysonderresourcenstatus == 1
                problemstellenvec=problemstellenvectmp;
                inds=indssort;
                anzahloptimierungsdurchgaenge=anzahloptimierungsdurchgaenge+1;
                updateresourcenstatus =1;
                tryagain = 0;
                trysonderresourcenstatus = 0;
                if berichtstatus == 1
                    disp([num2str(length(problemstellenvectmp)),' verbleibende Problemstellen...']);
                end
			else
                tryagain=1;
                updateresourcenstatus=0;
			end
            
            %resourcen updaten
            %-------------------
            if updateresourcenstatus==1
            
				resourcenstellenvec=[];
				indshelp=inds;
				if inds(1)~=1;indshelp=[-1,indshelp];end
				if inds(end)~=length(outmat);indshelp=[indshelp,length(outmat)+2];end
				diffinds=diff(indshelp);
				resourcenzaehler=1;
				naechsteserie=1;
				resourcenstellen=find(diffinds>3);
                sonderresourcen=find(diffinds==3);
                for q=1:length(sonderresourcen)
                    sonderresourcenstellenvec(q)=indshelp(sonderresourcen(q));
                end
				for i=1:length(resourcenstellen)
                    naechsteserie = 1;
                    serienabschnitte = 0;
                    while naechsteserie == 1
                        naechsteserie = 0;
                        serienzaehler = 1;
                        while serienzaehler<=anzahlwiederholungen & serienzaehler<diffinds(resourcenstellen(i))-2
                            resourcenstellenvec(resourcenzaehler)=indshelp(resourcenstellen(i))+1+serienzaehler+serienabschnitte;
                            resourcenzaehler=resourcenzaehler+1;
                            serienzaehler = serienzaehler + 1; 
                        end
                        if indshelp(resourcenstellen(i))+1+serienabschnitte + serienzaehler + 1 < indshelp(resourcenstellen(i)+1)-1
                            naechsteserie = 1;
                            serienabschnitte=serienabschnitte + serienzaehler;
                        end
                    end
				end
            end
		end
	
	
		% indsini;
		% inds;
		
		%Fehlermeldung
		%-------------
		if length(indsini)~=length(inds)
            if berichtstatus == 1
                uiwait(errordlg('Wiedersprüchliche Längen von initialen und transformierten Indicies in <optimizerepandfaktorausschluss.m>!','Achtung:'));
            end
            outmat = [];
            return
		end
        
		%reihe umschreiben
		%-----------------
        reihetmp=reihe;
		reihetmp(indsini)=[];
        
        for j=1:length(inds)
            reihetmp(end+1)=0;
            reihetmp(inds(j)+1:end)=reihetmp(inds(j):end-1);
            reihetmp(inds(j))=target;
        end
		
		%ausschluss überprüfen
		%------------------------
		ausschlussindmat=[];
		if ~isempty(faktorausschlussmat{target})
            for z=1:length(faktorausschlussmat{target})
                ausschlussindmat=[ausschlussindmat,find(reihetmp==faktorausschlussmat{target}(z))];
            end
            ausschlussindmat=sort(ausschlussindmat);
            targetmat=find(reihetmp==target);
            combimat=zeros(length(ausschlussindmat),length(targetmat));
            for z=1:length(ausschlussindmat)
                for y=1:length(targetmat)
                    if abs(ausschlussindmat(z)-targetmat(y))==1
                        combimat(z,y)=1;
                    end
                end
            end
            
            if isempty(find(combimat==1))
                erfolg=1;
            end
		end
        
        %Progress
        %----------
		erfolgloszaehler=erfolgloszaehler+1;
		if mod(erfolgloszaehler,80)==0
            if berichtstatus ==1
                answer = questdlg('<optimizerepandausschluss.m> wiederholt nicht erfolgreiche! Weitersuchen?','Optimierung:','ja','nein','debug','ja');
                if strcmp(answer,'debug')
                    dbstop if error
                    aensdlkjd
                elseif strcmp(answer,'nein')
                    outmat=[];
                    return
                end   
            else
                outmat=[];
                return
            end
		end   
	end
    
    reihe=reihetmp;
    %Gesamtausschluss überprüfen
	%------------------------
    erfolgsmat=[];
    for w=1:length(faktorausschlussmat)
		ausschlussindmat=[];
		if ~isempty(faktorausschlussmat{w})
            for z=1:length(faktorausschlussmat{w})
                ausschlussindmat=[ausschlussindmat,find(reihetmp==faktorausschlussmat{w}(z))];
            end
            ausschlussindmat=sort(ausschlussindmat);
            targetmat=find(reihetmp==target);
            combimat=zeros(length(ausschlussindmat),length(targetmat));
            for z=1:length(ausschlussindmat)
                for y=1:length(targetmat)
                    if abs(ausschlussindmat(z)-targetmat(y))<2
                        combimat(z,y)=1;
                    end
                end
            end
            if isempty(find(combimat==1))
                erfolgsmat(w)=1;
            end
		end
    end
    
   
    
    gesamterfolgloszaehler=gesamterfolgloszaehler+1;
    if mod(gesamterfolgloszaehler,20)==0
        fprintf('.');   
	end 
    
	if mod(gesamterfolgloszaehler,80)==0
        answer = questdlg('optimizerepandfaktorausschluss wiederholt nicht erfolgreiche! Weitersuchen?','Optimierung:','ja','nein','ja');
        if strcmp(answer,'nein')
            outmat=[];
            return
        end   
	end 

end
    
outmat = reihe;
return