% Input:
% qd: vector (containing the ids of all transitions starting in the
% considere location)
% omegas: cell array of function handles (support functions of the flowpipe)
% results: Matrix (matrix representation of the flowpipe)
% transitions: cell array of structs

% Output:
% x: vector (containing the sets which intersect the guards of the
% transition specified by the correspondent entry in transitiontotake)
% transitiontotake: vector (containing the ids of possible transitions

% Description:
% Finds the sets (vector x) from the flowpipe which intersect the guards of
% transitions (transitiontotake).

function [x,transitiontotake] = getSetsWithGuardIntersectionExt(qd,omegas,results,transitions)

transitiontotake = zeros(length(qd),1);
x = zeros(length(qd),length(omegas)); %true if there is a transition to take

N = length(omegas);

relevanttransitions = transitions(qd);

if length(omegas) == 1 && N ~= 1
    start = 1;
    N = 1;
else
    %start = 2;
    start = 1;
end;

nbr = 1;

if ~isempty(results)
    
    for j=1:length(qd)  % for all transitions
        y = [];
        if ~transitions{j}.spontaneous

            for   i=start:1:N %for all sets in flowpipe (ignore first)
                %result = results(:,i);
                if  testSetIntersectionFast(relevanttransitions{j},results(:,i)) % the set intersects all guards associated with transition j

                    if ~isempty(y) && y(end) ~= i-1
                        x(nbr,1:length(y)) = y;
                        transitiontotake(nbr,1) = qd(j);

                        x = [x; zeros(1,size(x,2))];
                        y = [i];
                        nbr = nbr +1;
                        transitiontotake(nbr,1) = qd(j);

                    else
                        transitiontotake(nbr,1) = qd(j);
                        y = [y i];
                    end;
                end;
            end;
        end;
        x(nbr,1:length(y)) = y;
        nbr = nbr +1; 
    end;
    
else
    
    for j=1:length(qd)  % for all transitions
        y = [];

        if ~transitions{j}.spontaneous
            for   i=start:1:N %for all sets in flowpipe (ignore first)

                if  testSetIntersectionOmega(relevanttransitions{j},omegas{i}) % the set intersects all guards associated with transition j

                    if ~isempty(y) && y(end) ~= i-1
                        x(nbr,1:length(y)) = y;
                        transitiontotake(nbr,1) = qd(j);

                        x = [x; zeros(1,size(x,2))];
                        y = [i];
                        nbr = nbr +1;
                        transitiontotake(nbr,1) = qd(j);

                    else
                        transitiontotake(nbr,1) = qd(j);
                        y = [y i];
                    end;
                end;
            end;
        end;

       x(nbr,1:length(y)) = y;
       nbr = nbr +1; 
    end;
    
end;


% delete complete 0 entries
delete = find(transitiontotake == 0);
ttemp = zeros(length(transitiontotake)-length(delete),1);
xtemp = zeros(length(transitiontotake)-length(delete),size(x,2));
next = 1;
for i=1:length(transitiontotake)
    if ~ismember(i,delete)
        ttemp(next) = transitiontotake(i);
        xtemp(next,:) = x(i,:);
        next = next +1;
    end;
end;

x = xtemp;
transitiontotake = ttemp;


% Input:
% transition: structure
% result: vector (containing evaluation results for every direction of a
% support function)

% Output:
% intersection: boolean

% Description:
% Fast version of testSetIntersectionOmega 
% can only be used if evaluations are available and uses the fact, that
% opposite directions have been evaluated by the flowpipe generation
% algorithm previously for the opposite(mirrored) directions, too.
function intersection = testSetIntersectionFast(transition,result)
intersection = sum(-result <= transition.G_star) == length(result);


% Input:
% transition: structure
% omega: function handle (support function)

% Output:
% intersection: boolean

% Description:
% tests if all equalityguards AND inequality guards from transition j
% intersect the set omega
function intersection = testSetIntersectionOmega(transition,omega)
intersection = true;
   
    if ~isempty(transition.dqq)
            for k=1:1:size(transition.dqq,2) % for all equality guards
                if ~intersection
                    break;
                end;
            
                if ~isnan(transition.eqq(k))    % transition is "usual" (non-spontaneous)        
                        intersection = intersection && -omega(-transition.dqq(:,k)) <= transition.eqq(k) &&  -omega(transition.dqq(:,k)) <= -transition.eqq(k);
                        %intersection = intersection && -omega(-transition.dqq(:,k)) <= transition.G_star(transition.eguard_constraints_in_L(k+length(transition.eqq))) &&  -omega(transition.dqq(:,k)) <= transition.G_star(transition.eguard_constraints_in_L(k));
                else
                    intersection = false;
                end;
            end;
    end;   
   
    if ~isempty(transition.diqq)        
            for k=1:1:size(transition.diqq,2) % for all inequality guards
                if ~intersection
                    break;
                end;
                    intersection = intersection && -omega(-transition.diqq(:,k)) <= transition.eiqq(k);
                    %intersection = intersection && -omega(-transition.diqq(:,k)) <= -transition.G_star(transition.mirrored_iguard_constraints_in_L(find(transition.iguard_constraints_in_diqq,k)));
            end;
    end;   
