clc
clear all
format compact
format longG
iName ='misex1';
benchName = sprintf('%s.pla',iName);
benchMorphed = sprintf('%sMorphed.pla',iName);

fileID = fopen(benchName, 'r' , 'n', 'windows-1254');
% fileIDm = fopen(benchMorphed,'w+');
fileIDcom = fopen('command.txt','w');
comText =sprintf('cec %s %s',benchName,benchMorphed);
fprintf(fileIDcom,comText);
tic

global Po
global Pc
global input
global output
global IR
functionSort = 'simple';
crossSort = 'simple';

Po = 0.04;
Pc = 0.12;
Pw = 0.0;


if Po >= Pc
    morphing = false;
else
    morphing = true;
end
morphing = true;

morphCase = 1;    % 1: full, 2: double 3: single morphing
IRmax = 0;

sampleSize = 200;
validMappingH = 0;
noMappingH = 0;
spaceAscii = 32; % abs(x) produce a 10 for space (. in notepad++) character.
returnAscii = 10; % abs(x) produce a 10 for return (LR in notepad++) character.
totalMorph = false;
B = fscanf(fileID, '%c');

counter = 1;
for k=1:20
    if abs(B(k)) == 10 || abs(B(k)) == 32
        check(counter) = k;
        counter = counter +1;
    end
    if counter >2
        input = B(check(1):check(2));
        input = str2num(input)
        break
    end
end

counter = 1;
check=[];

for t=k+1:20
    if abs(B(t)) == 10 || abs(B(t)) == 32
        check(counter) = t;
        counter = counter+1;
    end
    if counter >2
        output = B(check(1):check(2));
        output = str2num(output)
        preLimit = t;
        break
    end
end

products = numel(B(preLimit+1:end-3)) / (input+output+2);
prodMatrix = B(preLimit+1:end-3);

outputCell = cell(output,1);
range = input + output +2;
if IRmax == 0
    [IRmax,vector] = thresholdIR(input)
end



temp =[];
for t=1:products
    temp = [temp;prodMatrix((t-1)*range+1:(t-1)*range+range)];
end
prodMatrix = temp;


nMorph =1;
morphVector =[];
morphedProdMatrix =[];

for i = 1:products
    
    temp = prodMatrix(i,:);
    %    temp = prodMatrix((i-1)*range +1 : i*range);
    litCount = sum(temp(1:input) ~='-');
    isMorphed = litCount < IRmax;
    outputProducts = find(temp(input+2:range-1) == '1');
    
    if isMorphed
        morphedProdMatrix(nMorph,:) = [i litCount outputProducts zeros(1,output-numel(outputProducts))];
        isMorphed =false;
        nMorph = nMorph+1;
    end
    
    for t = outputProducts
        outputCell{t} = [outputCell{t}; temp];
    end
    
end

if ~isempty(morphedProdMatrix) && morphing    
    morphedProdMatrix = sortrows(morphedProdMatrix,2)
    
    if size(morphedProdMatrix,1) > 100
        morphedProdMatrix = morphedProdMatrix(1:100,:);
    end
    oneList = [];
    for t=1:output
        [temp,~] = size(outputCell{t});
        if temp == 1
            oneList =[oneList t];
        end
    end
    
    if numel(oneList) >0
        elRows =[];
        for t=1:size(morphedProdMatrix,1)
            temp = morphedProdMatrix(t,3:end);
            for i = oneList
                if any(i == temp)
                    elRows = [ elRows t];
                end
            end
        end
        morphedProdMatrix(elRows,:) =[];
    end
    
    tempAdd=B;
    
    for t=1:size(morphedProdMatrix,1)
        
        iProduct = morphedProdMatrix(t,1);
        product = prodMatrix(iProduct,:);
        product = product(1:input);
        outputs = morphedProdMatrix(t,3:end);
        litRoom = IRmax - morphedProdMatrix(t,2);
        outputs(outputs == 0) =[];
        outputRange =[];
        
        for i=outputs
            outputRange =[outputRange size(outputCell{i},1)];
        end
        
        [~,temp] = min(outputRange);
        iOutput = outputs(temp);
        
        if litRoom ==1
            initial = litRoom;
            last = litRoom;
        else
            switch morphCase
                case 1
                    initial = litRoom;
                    last=1;
                case 2
                    initial = litRoom;
                    last = litRoom-1;
                case 3
                    initial = litRoom;
                    last = litRoom;
            end
        end
        
        for j=initial:-1:last
            
        if totalMorph
            if input <10
                nProducts = pgenerator(product,outputCell{iOutput},litRoom);
            else
                nProducts = pgeneratorlim(product,outputCell{iOutput},litRoom); % Product Generator
            end
        else
            nProducts = pgeneratorlim(product,outputCell{iOutput},litRoom); % Product Generator
        end
        
        temp = tempAdd;
         matching = false;
         
        for i=size(nProducts,1):-1:2
            fileIDm = fopen(benchMorphed,'w');
            temp(preLimit +(iProduct-1)*range+1:preLimit +(iProduct-1)*range +input) = nProducts(i,:);
            fprintf(fileIDm,temp);
            [a,b] = system('abc10216 -f command.txt');
            if (i ==size(nProducts,1)) && t==1
%                 b
            end
            size(b);
            if size(b,2) == 25
%                 iProduct
                display('EUREKA')
                matchig = true;
                tempAdd = temp;
                break
            end
            temp=tempAdd;
            fclose(fileIDm);
        end
        if matching
            break
        end
        litRoom = litRoom-1;
        end
        
    end
    
    nanoPla = vec2mat(tempAdd(preLimit+1:end-3),input+output+2);
    nanoPla = nanoPla(:,1:input);
    FM = zeros(products,2*input);
    
    for k=1:numel(nanoPla)
        check = nanoPla(k);
        switch check
            case '1'
                FM(k) = 1;
            case '0'
                FM(k+numel(nanoPla)) = 1;
        end
    end
    
else
    
    nanoPla = vec2mat(B(preLimit+1:end-3),input+output+2);
    nanoPla = nanoPla(:,1:input);
    FM = zeros(products,2*input);
    
    for k=1:numel(nanoPla)
        check = nanoPla(k);
        switch check
            case '1'
                FM(k) = 1;
            case '0'
                FM(k+numel(nanoPla)) = 1;
        end
    end
    
end

fclose('all');
morphTime = toc;
[M, N] = size(FM);
if M < N
    FM = FM';
    [M, N] = size(FM);
end

IR = sum(sum(FM == 1)) / (M*N);
FM(FM == 0) = -1;

rowC = ceil(1.5*M);
columnC = ceil(1.5*N);



for k=1:sampleSize
    tic
    fprintf(' k = %d\n', k)
    valid_mapping = false;
    
    
    CM = randsrc(rowC, columnC, [1 0 -1; Pc (1 -Po -Pc) Po]);
    wire_bridging = randsrc(1, rowC, [ 1 0; Pw 1-Pw])';
    if sum(sum(wire_bridging)) >0
        wire_pos = find(wire_bridging == 1);
        CM(wire_pos,:) = [];
    end
    
    
    cSub = CM;
    fSub = FM;
    
    cSub = matrix_sortT(cSub, 'cut', N);
    
    
    fSub = matrix_sortT(fSub, functionSort,0);
    cSub = matrix_sortT(cSub, crossSort,0);
    
    for perm=1:2
    [rowMatch,assign] = backtrack_failsafe(fSub,cSub);
    
    if all(rowMatch(1,:) > 0)
        valid_mapping = true;
        dominant = 1;
        break
    end
    fSub = fSub(:,randperm(size(fSub,2)));
    end
    T = toc;
    
    fprintf(' Heuristic Runtime = %0.4f\n',T)
    
    timeVectorHeuristic(1,k) = T;
    
    if valid_mapping
        display('Valid Mapping')
        validMappingH = validMappingH +1;
    else
        display('No Mapping')
        noMappingH = noMappingH + 1;
    end
    
end

fprintf('_______________________________________________\n\n')
fprintf('Logic Inclusion Ratio = %f\n\n', IR)
fprintf('Function Size (%d x %d) = %d\n\n', M, N, M*N)
fprintf('Crossbar Size (%d x %d) = %d\n\n', rowC, columnC, rowC*columnC)
fprintf('Number of Valid Mappings = %d\n', validMappingH)
fprintf('\n')
fprintf('Number of Failed Mappings = %d\n', noMappingH);
fprintf('\n')
meanH = validMappingH*100 /sampleSize;
meanH=floor(meanH);
fprintf('Percentage of Valid Mappings for Heuristic = %d\n\n', meanH);
singleTime = (sum(timeVectorHeuristic)+morphTime) / 200;
fprintf('Time for each Sample for Heuristic = %f\n', singleTime)
fprintf('input = %d and IRmax = %d\n',input,IRmax)