No BSD License  

Highlights from
MatPlanWDM v0.5

image thumbnail

MatPlanWDM v0.5

by

 

29 Jan 2007 (Updated )

Educational network planning tool for the RWA problem in WDM networks (MILP and heuristic based)

libraryGraph_kshortestPath.m
% libraryGraph_kshortestPath
%
% Usage: [cellOfKPaths] = libraryGraph_kshortestPath
% (k, linkTable, ingressNode, egressNode)
%
% Abstract: This function computes the "K" different shortest paths between
% a pair of nodes (ingress node, egress node). A shortest path is defined
% as the path with the minimum total weight (or cost), where the total
% weight is the sum of the weights of the links which the path consist of. 
% If there are only "X" shortest paths between ingress node and egress
% node, where "X" < "K" (K is the demanded number of shortest paths), the
% function returns the "X" found shortest paths, and empty matrices up to
% reach the number "K". The implementation of this function is based on the
% K-shortest path algorithm proposed in :
% [1]	E.Q. Martins, An algorithm to ranking paths that may contains
% cycles, European Journal of Operational Research, vol. 18, pp. 123-130,
% 1984
%
% Arguments:
% o	In: 
%    k: Integer number. Demanded number of shortest paths between ingress
%     node and egress node.
%
%    linkTable(L,3): Matrix of L physical links by 3. Each row is a
%     physical link 'l', where the first and second columns of each row are
%     the nodeID (integer number) of the origin node 'x' and the nodeID
%     (integer number) of the destination node 'y' of this link 'l'
%     respectively. The third column is the link weight of the link 'l'.
%
%    ingressNode: Origin Node of the path.
%
%   . egressNode: Destination Node of the path.
%   
% o	Out:
%    cellOfKPaths(K,1): K-by-3 cell of vectors. Each row is one of the "K"
%     shortest paths. The rows (shortest paths) are sorted in decreasing
%     weight (or cost). Each row consist of the three columns:
%       - 1st) sequenceOfSPFLinkIds: Row vector with the sorted sequence of
%         IDs of the links which the shortest path between ingress and
%         egress consist of. The links IDs are sorted from the ingress node
%         to the egress node.
%       - 2nd) sequenceOfSPFNodeIds: Row vector with the sorted sequence of
%         IDs of the nodes which the shortest path  between ingress
%         and egress consist of. The nodes IDs are sorted from the ingress
%         node to the egress node.
%       - 3rd) totalCost: It is the total weight of the shortest path found
%         between ingress and egress. It is computed as the sum of the
%         weights of the links which the shortest path consist of.
%
%


function [cellOfKPaths] = libraryGraph_kshortestPath (k,linkTable,ingressNode,egressNode)
    
    cellOfKPaths = cell(k,3);

    % first we compute for k=1
    [spfk1_sequenceOfLinkIds , spfk1_sequenceOfNodeIds , totalCost] = libraryGraph_shortestPath (linkTable , ingressNode , egressNode);
       
    if (length(spfk1_sequenceOfLinkIds) == 0)
        disp ('There is no path');
        return
    end

    cellOfKPaths{1,1} = spfk1_sequenceOfLinkIds;
    cellOfKPaths{1,2} = spfk1_sequenceOfNodeIds;
    cellOfKPaths{1,3} = totalCost;

    if k == 1
        return;
    end

    originalGraph_maxNodeNumber = max(max(linkTable(:,1:2)));
    originalGraph_maxLinkNumber = size(linkTable,1);

    % coord i is the orginal node which this node is mirror of
    % coord i belongs to [1...maxNodeNumberK1]
    % there are as many coordinates as different nodes

    previousSPF_sequenceOfLinkIds = spfk1_sequenceOfLinkIds;
    previousSPF_sequenceOfNodeIds = spfk1_sequenceOfNodeIds;
    previousGraph_physLinkTable = linkTable;
    previousGraph_nodeMirrors = -1 * ones (1,originalGraph_maxNodeNumber); % the nodes that are mirror nodes from itself, are put to -1
    previousGraph_linkMirrors = -1 * ones (1,originalGraph_maxLinkNumber); % the links that are mirror nodes from itself, are put to -1

    for currentK=2:k  
        
        [previousSPF_intermediateLinkIdsPathToRemove,previousSPF_intermediateNodeIdsPathToRemove]  = sequenceOfIntermediateNodesAndLinks (previousSPF_sequenceOfLinkIds , previousSPF_sequenceOfNodeIds);
        
        currentGraph_physLinkTable = previousGraph_physLinkTable;
        currentGraph_nodeMirrors = previousGraph_nodeMirrors;% vector. The component i is the id of the node which the node i is mirror of. It is -1 if the node i is no mirror from anyone
        currentGraph_linkMirrors = previousGraph_linkMirrors;% vector. The component i is the id of the link which the link i is mirror of. It is -1 if the link i is no mirror from anyone
                                                             
        % step 1 and 2: create the mirror nodes to the intermediate nodes, and the mirror intermediate links 
        % step 3: 
        for contIntermediateNode=1:length(previousSPF_intermediateNodeIdsPathToRemove)
 
            originalNodeId = previousSPF_intermediateNodeIdsPathToRemove (contIntermediateNode);
            mirrorNodeId = length (currentGraph_nodeMirrors) + 1;
            currentGraph_nodeMirrors = [currentGraph_nodeMirrors originalNodeId];

            if contIntermediateNode > 1
                % mirror intermediate links of the path
                previousGraph_linkIdToMirror = previousSPF_intermediateLinkIdsPathToRemove (contIntermediateNode - 1);            
                currentGraph_sourceNodeLinkToAdd = length(currentGraph_nodeMirrors)-1;
                currentGraph_targetNodeLinkToAdd = length(currentGraph_nodeMirrors);
                currentGraph_weightLinkToAdd = currentGraph_physLinkTable (previousGraph_linkIdToMirror , 3);

                currentGraph_physLinkTable = [currentGraph_physLinkTable ; currentGraph_sourceNodeLinkToAdd currentGraph_targetNodeLinkToAdd currentGraph_weightLinkToAdd];
                currentGraph_linkMirrors = [currentGraph_linkMirrors previousGraph_linkIdToMirror];
            end

            % step 3: change the arcs that direct to the original internal nodes,
            % to direct to their mirrors (except the arcs of the path)
            linkIdsTargetedToOriginalIntermediateNodeId = find (previousGraph_physLinkTable(:,2) == originalNodeId);
            for contLinkIdToChange=1:length(linkIdsTargetedToOriginalIntermediateNodeId)
                linkIdToChange=linkIdsTargetedToOriginalIntermediateNodeId(contLinkIdToChange);
                %if the node does not belong to the path to delete, then we
                %link it.
                if (isempty (find (previousSPF_sequenceOfLinkIds==linkIdToChange)))
                    currentGraph_physLinkTable (linkIdToChange,2) = mirrorNodeId;
                end
            end
        end

       % step 4: move an arc
       if (length (previousSPF_intermediateLinkIdsPathToRemove) == 0)
           % If the path to delete was a single-hop path, there is no
           % intermediate links neither intermediate nodes. For this
           % reason, we must create a imaginary mirror node so that the
           % step 4 can works correct.
           currentGraph_nodeMirrors = [currentGraph_nodeMirrors -1];
       end
        lastLinkIdOfPath = previousSPF_sequenceOfLinkIds (end);
        currentGraph_physLinkTable (lastLinkIdOfPath , 1) = length (currentGraph_nodeMirrors); % enlazo ultimo link del camino a borrar, tal que ahora provenga del ultimo nodo espejo creado
       
        % calculate the spf in the new graph
        [spfkcurrent_sequenceOfLinkIds , spfkcurrent_sequenceOfNodeIds , totalCost] = libraryGraph_shortestPath (currentGraph_physLinkTable , ingressNode , egressNode);    

        if isempty (spfkcurrent_sequenceOfLinkIds)
            return;
        end
               
        % convert the mirror node ids found in the links and nodes, to their
        % original values
        spfToReturn_sequenceOfLinkIds = convertMirrorIds (spfkcurrent_sequenceOfLinkIds , currentGraph_linkMirrors , originalGraph_maxLinkNumber);
        spfToReturn_sequenceOfNodeIds = convertMirrorIds (spfkcurrent_sequenceOfNodeIds , currentGraph_nodeMirrors , originalGraph_maxNodeNumber);

        % add the new spf path to the cell
        cellOfKPaths{currentK,1} = spfToReturn_sequenceOfLinkIds;
        cellOfKPaths{currentK,2} = spfToReturn_sequenceOfNodeIds;
        cellOfKPaths{currentK,3} = totalCost;

        exitFlag = checkPath (spfToReturn_sequenceOfLinkIds , spfToReturn_sequenceOfNodeIds , linkTable , ingressNode , egressNode);
        if (exitFlag == -1) ||(cellOfKPaths{currentK-1,3}>totalCost)
            disp ('Error: checkpath: no son un camino de origen a destino o el coste es mejor y no peor');
            spfToReturn_sequenceOfLinkIds
            spfToReturn_sequenceOfNodeIds
            pause
        end
        

        previousSPF_sequenceOfLinkIds = spfkcurrent_sequenceOfLinkIds;
        previousSPF_sequenceOfNodeIds = spfkcurrent_sequenceOfNodeIds;
        
        previousGraph_physLinkTable = currentGraph_physLinkTable;
        previousGraph_nodeMirrors = currentGraph_nodeMirrors;
        previousGraph_linkMirrors = currentGraph_linkMirrors;
    end
end


function [convertedSequence] = convertMirrorIds (sequence , mirrorTable , originalGraph_maxNodeNumber)
    convertedSequence = sequence;
    for contId=1:length (sequence)
        while (convertedSequence (contId) > originalGraph_maxNodeNumber)
            convertedSequence (contId) = mirrorTable (convertedSequence (contId));
        end
    end
end


function [intermLinkIdSequence,intermNodeIdSequence] = sequenceOfIntermediateNodesAndLinks (sequenceOfLinkIds , sequenceOfNodeIds)
   if length(sequenceOfNodeIds) <= 2
        intermNodeIdSequence = [];
        intermLinkIdSequence = [];
        return
   elseif length(sequenceOfNodeIds) == 3
        intermNodeIdSequence = sequenceOfNodeIds (2);
        intermLinkIdSequence = [];
   else
        intermNodeIdSequence = sequenceOfNodeIds (2:end-1);
        intermLinkIdSequence = sequenceOfLinkIds (2:end-1);
   end       
end

function [exitFlag] = checkPath (sequenceLinkIds , sequenceNodeIds , linkTable , ingressNode , egressNode)
exitFlag = -1;
if (sequenceNodeIds(1) ~= ingressNode) || (sequenceNodeIds(end) ~= egressNode)
    return;
end

for contLinkId=1:length(sequenceLinkIds)
    linkId = sequenceLinkIds (contLinkId);
    linkSourceNode = linkTable(linkId,1);
    linkTargetNode = linkTable(linkId,2);
    % the origin node and the destinatio node are the nodes that
    % corresponds to sequenceNodeId
    if (linkSourceNode ~= sequenceNodeIds (contLinkId)) || (linkTargetNode ~= sequenceNodeIds (contLinkId+1))
        return;
    end
end

exitFlag = 0;

end

Contact us