/**
* @copyright 2013 Computer Science Department, Recursive InterNetworking Architecture (RINA) laboratory, Boston University.
* All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation
* for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all
* copies and that both the copyright notice and this permission notice appear in supporting documentation.
* The RINA laboratory of the Computer Science Department at Boston University makes no
* representations about the suitability of this software for any purpose.
*/
package rina.routing.util;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
/**
* Link State Routing
*/
/**
*
* @author Yuefeng Wang. Computer Science Department, Boston University
*
*/
public class Dijkstra {
/**
* build Forwarding Table
* @param map
* @param source
* @return map
*/
public static LinkedHashMap<Integer,Integer> buildForwardingTable(LinkedHashMap<Integer,Integer> FT, LinkedHashMap<Integer,LinkedHashMap <Integer, Double>> map, int source)
{
FT.clear();
int [] all_node= LinkedHashMapKeyToArray(map);
int numNode = all_node.length;
double inf= (double) 999999999;
int [] neighbour = LinkedHashMapKeyToArray((LinkedHashMap <Integer, Double>)map.get(source));
double [] neighbourDis = LinkedHashMapValueToArray((LinkedHashMap <Integer, Double>)map.get(source));
int nunNeighbour= neighbour.length;
LinkedHashMap<Integer,Double> Dis= new LinkedHashMap<Integer,Double>();//store the distance to all other nodes in the map
LinkedHashMap<Integer,Integer> Previous_Node = new LinkedHashMap<Integer,Integer>(); //store the previous to the source
//// all nodes to the source is inf
for(int i=0;i<numNode;i++)
{
if( all_node[i] != source)
{
Dis.put(all_node[i], inf );
Previous_Node.put(all_node[i], source);
}
}
//// update the neighbour of the source
for(int i=0;i<nunNeighbour;i++)
{
Dis.put(neighbour[i], neighbourDis[i]);
Previous_Node.put(all_node[i], source);
}
//Initialisation finished
//now start to build the Forwarding Table
while(FT.size()!=(numNode-1))// not all node are in the set FT
{
int min = MinDisKey(Dis); // find the node with min distance in NOT FT
double minDis= Dis.get(min);
int next_hop =source;
// System.out.println("map.get(source):" + map.get(source));
// System.out.println("min is " + min);
// System.out.println("Previous_Node.containsKey(min): " + Previous_Node.containsKey(min));
// System.out.println("Previous_Node:" + Previous_Node);
int previous_hop = Previous_Node.get(min);
LinkedList<Integer> this_path = new LinkedList<Integer>() ;
if( previous_hop ==source )
{
next_hop = min;
this_path.add(min);
}
else
{
while(previous_hop != source)
{
this_path.add(previous_hop);
next_hop=previous_hop;
previous_hop= Previous_Node.get(previous_hop);
}
}
////////////////////////////////////////////////////////////////////
//TESTME remove the islocated node
// System.out.println("pppppppppppppppppppppppppPrevious_Node" + Previous_Node ) ;
//Done
///////////////////////////////////////////////////////////////////
// System.out.println("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzthis_path is " + this_path);
FT.put(min, next_hop);
//////////////
// now stat to update the Dis for all node that not in the FT
int minNeighbourNum= ( (LinkedHashMap)map.get(min) ).size();
int [] minNeighbour = LinkedHashMapKeyToArray((LinkedHashMap)map.get(min));
double [] minNeighbourDis = LinkedHashMapValueToArray((LinkedHashMap)map.get(min));
double disViaMin;
for(int i=0;i<minNeighbourNum;i++)
{
if(FT.containsKey(minNeighbour[i])==false && ( minNeighbour[i] != source))
{
// System.out.println("minNeighbour[i]: " + minNeighbour[i] );
// System.out.println("Dis.containsKey(minNeighbour[i]):" + Dis.containsKey(minNeighbour[i]));
// System.out.println("map.containsKey(minNeighbour[i]):" + map.containsKey(minNeighbour[i]));
double current_dis = Dis.get(minNeighbour[i]);
disViaMin = minDis + minNeighbourDis[i];
if(disViaMin< current_dis)
{
Dis.put(minNeighbour[i], disViaMin);
Previous_Node.put(minNeighbour[i],min);
}
}
}
Dis.remove(min);//remove min from the NOT FT list;
}
//return FT;
/////////////////////////////////////////////////////////////////
// neighborSet is used to clean the FT as there is outdated info,
//so remove any dst from FT if its next hop is not direct neighbor
//FIXME:maybe also clean the map
/////////////////////////////////////////////////////
Set<Integer> neighborSet = map.get(source).keySet();
/////////////////////////////////////////////////////
return cleanForwardingTable(FT,neighborSet);
}
private static LinkedHashMap<Integer,Integer> cleanForwardingTable(LinkedHashMap<Integer,Integer> FT, Set neighborSet)
{
int[] keyArray = LinkedHashMapKeyToArray(FT);
for(int i = 0; i< keyArray.length ; i++)
{
int nextHop = FT.get(keyArray[i]);
if( ! neighborSet.contains(nextHop))
{
FT.remove(keyArray[i]);
System.out.println("cleanForwardingTable, " + keyArray[i] + " is removed, " +
"as its next hop " + nextHop + " is not source's neighbor");
}
}
return FT;
}
/**
* convert LinkedHashMap Key To Array
* @param map
* @return array
*/
private static int[] LinkedHashMapKeyToArray( LinkedHashMap hp)
{
int num = hp.size();
int[] keyArray= new int[num];
Object [] array ;
array = hp.keySet().toArray();
for(int j =0;j< num;j++)
{
keyArray[j] = Integer.parseInt(array[j].toString());
}
return keyArray;
}
/**
* LinkedHashMap Value To Array
* @param hash map
* @return array of int
*/
private static double[] LinkedHashMapValueToArray( LinkedHashMap <Integer, Double> hp)
{
int [] key = LinkedHashMapKeyToArray(hp);
int num = hp.size();
double[] valueArray= new double[num];
for(int j =0;j< num;j++)
{
valueArray[j] = hp.get(key[j]);
}
return valueArray;
}
/**
* Minimum Distance Key
* @param map
* @return minimum distance
*/
private static int MinDisKey(LinkedHashMap hp)
{
int min;
int n=hp.size();
int[] key = LinkedHashMapKeyToArray(hp);
double[] value = LinkedHashMapValueToArray(hp);
//bubble sort
int minKey=key[0];
double minValue= value[0];
for(int j=0;j<n;j++)
{
if(value[j] < minValue)
{
minKey = key[j];
minValue = value[j];
}
}
min=minKey;
return min;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}