Tsp-Shortest Path-Route-Finding-With-An-Elaborate-Text-File-Csv-Format-Reader
Tsp-Shortest Path-Route-Finding-With-An-Elaborate-Text-File-Csv-Format-Reader
File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.net.URL;
import java.io.InputStream;
import java.util.Scanner;
//---
/*
* An algorithm to find the shortest
closed loop of a tour of the US cities.
* EEDP Algorithms II:March 2011
* Caesar & Umang
*This note was added on Nov 12 2019 as
*I was uploading this document on
*scribd: I wrote this Java version—and
*Umang wrote his version in C language.
*/
public class HelloWorld {
public static void main(String[]
args ) throws Exception
{
long
startTime=System.currentTimeMillis();
im.lengths=
reader.readDistMatrix("alg2data/TSP_Da
ta.csv");
im.columnNames=reader.readCityNames
("alg2data/TSP_Data.csv",
im.lengths[0].length);
//("alg2data/TSP_Data.csv",
im.lengths[0].length);
double
minCost=99999999999.0;//we can think
of a better of way of initializing
these following 2 values
double minCost2=99999999999.0;
//@TO DO:
//We could parallelize the
following independent executions
//
//How it works:
//Each node/city is taken, in
turn, as a starting node- and the
shortest path algorithm is
//invoked. The shortest closed
loop (option 1 or option 2 -- pending
clarification) is the returned.
//
======================================
======================================
======================================
===============
//
======================================
======================================
======================================
===============
if(net.perm[net.perm.length-
1].distancePortion <minCost) //option
1- we'll seek clarification whether
it's option 1 required, or option 2
below
{
totalCost=
GraphOutput.getClosedLoopCost(net.perm
);
minCost=net.perm[net.perm.length-
1].distancePortion;
cheapestRoute=net.perm;
}
for(int m=1;
m<im.columnNames.length; m++)
//im.columnNames.length is the number
of nodes/cities
{
net=new Network(im, m,
net.perm[net.perm.length-
1].distancePortion);
if( net.perm.length
==im.columnNames.length &&
net.perm[net.perm.length-
1].distancePortion <=minCost)
//option 1- we'll seek clarification
whether it's option 1 required, or
option 2 below
{
totalCost=
GraphOutput.getClosedLoopCost(net.perm
);
minCost=net.perm[net.perm.length-
1].distancePortion;
cheapestRoute=net.perm;
//System.out.println("
Attempting to compute shortest path
starting at "+ im.columnNames[m] +"...
NEW SHORTEST PATH FOUND at " +
net.perm.length);
}
{
//System.out.println("
Attempting to compute shortest path
starting at "+ im.columnNames[m] +"...
Aborted at " + net.perm.length);
}
}
//end of parallelization
//
======================================
======================================
======================================
===============
//
======================================
======================================
======================================
===============
String LS =
System.getProperty("line.separator");
}
writer.close();
System.out.println("... DONE.
See output in TSP/alg2output");
}
}
/*
*
* Class defines the column names and
lengths
*/
class InputMatrix
{
static String[] columnNames=null;
static double [][] lengths=null;
}
//Add the other classes
class PDReader {
ArrayList<ArrayList<Double>> pd
= new ArrayList<ArrayList<Double>>();
BufferedReader input= new
BufferedReader(new
FileReader(fileName));
String s =
input.readLine();//read and ignore
this first row
s = input.readLine(); //now
start from here - row 1
int instance = 0;
while ((s != null))
{
pd.add(new
ArrayList<Double>());
StringTokenizer st = new
StringTokenizer(s, ",");
int count=0;
while (st.hasMoreTokens())
{
if(count<2)
{
String n
=st.nextToken();
}
else
{
pd.get(instance).add((Double.parseD
ouble((st.nextToken()).toString())));
}
count=count+1;
}
instance=instance+1;
s = input.readLine();
}
lengths[i][j]=pd.get(i).get(j);
}
return lengths;
}
public String[]
readCityNames(String fileName, int len)
throws IOException
{
String[] cityNames=new
String[len];
BufferedReader input= new
BufferedReader(new
FileReader(fileName));
String s =
input.readLine();//read 1st row
StringTokenizer st = new
StringTokenizer(s, ",");
String n =st.nextToken(); // we
don't want the first token, "Cities"
int count=0;
while (st.hasMoreTokens())
{
cityNames[count]=st.nextToken();
cityNames[count]=cityNames[count]+",
"+st.nextToken();
count++;
}
return cityNames;
//also added
/*
* This class defines the special
attributes of any node in a network
*
*/
class NodeEntry
{
String nodeName;
String nodeLabel; //unlabeled,
tentative or permanent
double distancePortion;
//Cumulative distance to a node, -1 if
undetermined
String prevNode; //previous node,
initially set to "-"
//-----
/*
* Implementation of shortest path
algorithm, otherwise also known as the
"labeling procedure"
* The following class defines a set
of rules for instantiating
* the nodes in a given (transport)
network, and contains methods for
* implementing the Shortest Path
Algorithm or Dijkstra's procedure
*/
class Network
{
//change this
int graphSize;
NodeEntry[] node;;
static NodeEntry[] tempCpy;;
static double[][] directLength;;
//declaration of an array to
temporarily store remaining nodes
NodeEntry[] temp =null;
for(int i=0;i<node.length;i++)
{
node[i]=new
NodeEntry(im.columnNames[i],"un",-1,"-
");
}
for(int row=0;
row<directLength.length; row++)
{
for(int col=0;
col<directLength.length; col++)
directLength[row][col]=im.lengths[r
ow][col];
}
perm=new NodeEntry[node.length];
temp =new NodeEntry[node.length];
/*
* make a cpy of the node names in
their resp position
* before any destruction is done
by Dijkstra's procedure
*
*/
void dupCpy()
{
for(int i=0;i<node.length;i++)
{
tempCpy[i]=new
NodeEntry(node[i].nodeName,node[i].nod
eLabel,node[i].distancePortion,node[i]
.prevNode);
}
}
/*
* method to set source and
destination as selected as input by
user
*
*/
public void get_S_and_D(String
source, String dest)
{
currentLoc=source;
destination=dest;
}
/*
* method to label source (node)
permanent, or "perm"
*
*/
public void setSourcePermanent()
{
for(int i=0;i<node.length;i++)
{
if(node[i].nodeName.equals(currentL
oc))
{
node[i].nodeLabel="perm";
//set source node permanent
node[i].prevNode="S"; //S
denotes "source"
node[i].distancePortion=0;
//
}
}
}
/*
*
* method to copy permanent node
details from node array into perm
array
* Each new permanent node element
is added to the next empty slot in
perm
*/
if(node[i].nodeLabel.equals("perm"))
{
{
perm[currentPermIndex()+1]=
new
NodeEntry(node[i].nodeName,node[i].nod
eLabel,node[i].distancePortion,node[i]
.prevNode);
}
}
}
}
/*
*
* method to copy and return the
non-permanent node array elements
*/
NodeEntry[] remainder()
{
temp=new NodeEntry[node.length-
1];
int k=0;
for(int i=0; i<node.length;i++)
{
if(!(node[i].nodeLabel.equals("perm
")))
{
temp[k]=new
NodeEntry(node[i].nodeName,
node[i].nodeLabel,
node[i].distancePortion,
node[i].prevNode);
k++;
}
}
return temp;
}
/*
* method to determine and return
the index of the most recently
* added element in the perm array
(list).
* A new permanent node,if any, is
added the next slot
*
*/
int currentPermIndex()
{
for(int i=0;i<perm.length;i++)
{
if(perm[i]==null)
return i-1; //(i-1) is the
index of last-in element so far; it's
all null after this
}
return -1;
}
if(perm[index].nodeName.equals(temp
Cpy[i].nodeName))
{
return i;
}
}
return -1;
}
if(name.equals(tempCpy[i].nodeName))
{
return i;
}
}
return -1;
/*
*
* method to remove the permanent
node from the previous nodes array
*/
/*
* method to determine whether a
given node in the remaining nodes
array
* has direct link to the "current"
permanent node
* This is based on the value of
distance in the distance grid
* A positive distance means
"direct link" exists
*/
boolean isDirectNode(int sub)
{
if((directLength[directRow(currentP
ermIndex())]
[directCol(node[sub].nodeName)])>0)
{
return true;
}
return false;
}
/*
*
* method to revise the tentatively
labeled (temporary) node elements
*/
public void revise()
{
if(numberOfRemainingNodes()>=2)
{
int
x=directRow(currentPermIndex());
//Now from the second
iteration, the link/distance (in
directLength 2-D)
// between the current
permanent node and the node labeled
permanent
//in the preceding iteration
is no longer needed. It may be
discarded.
// Here,it's flagged with the
special integer value,0. Any neg,
other
//than -1 would do.
int z;
//revise all direct nodes
for(int i=0;i<node.length;i++)
{
if(isDirectNode(i))
{
z=directCol(node[i].nodeName);
{
node[i].distancePortion=
perm[currentPermIndex()].distancePorti
on + directLength[x][z];
node[i].prevNode=
perm[currentPermIndex()].nodeName;
}
}
}
}
}
/*
* method to determine and return
the first node slot which contains
* a positive value of cumulative
distance, it is an optimization
* algorithm, saving the caller
from testing for 'positivity' of all
such slot entries
*
*/
int firstPosIndex()
{
for(int i=0;i<node.length;i++)
{
if(node[i].distancePortion>0)
return i;
}
return -1;
}
/*
* method to determine and return
the index of the slot containing the
* minimum (positive) cumulative
distance from the remaining nodes
array
* 1.initializing i to
firstPosIndex() value is an
optimization strategy
* 2.initializing minimum ensures
exact correctness
*
*/
minimum=node[i].distancePortion;
}
}
return minimum;
}
/*
* method to determine and return
index of the min of the revised nodes
*/
int minIndex()
{
for(int i=0;i<node.length;i++)
{
if(node[i].distancePortion==min())
return i;
}
return -1;
}
/*
* method to label a new node
permanent or "perm", basing on the
minimum
* value of the cumulative
distances of the node. Check the
series of
* method calls in this method
activation
*
*/
public void setNewPermNode()
{
//set new permanent node
for(int i=0;i<node.length;i++)
{
if(node[i].distancePortion==min())
{
node[minIndex()].nodeLabel="perm";
}
}
}
/*
* method to return the number of
nodes remaining in a given iteration
*/
public int numberOfRemainingNodes()
{
return node.length;
}
/*
* method to determine and return
the perm node that has the shortest
* direct path to the next
specified perm node as determined by
the
* Dijkstra's rule for given a
source-destination problem
*/
int prevNodeIndex(String
currentNodeName)
{
if( node.length==1) //base case
perm[perm.length-1]=new
NodeEntry(node[0].nodeName,node[0].nod
eLabel,node[0].distancePortion,node[0]
.prevNode);
//the following executes only n-
1, where n=number of the network nodes
for(int j=0;j<perm.length;j++)
{
if(perm[j].nodeName.equals( current
NodeName))
return j;
}
return -1;
}
/*
* method to invoke all the methods
in some sequence to implement
Dijkstra's procedure
*/
double minTotalCost=999999999.0;
NodeEntry[] leastCostPath=perm;
void runDijkstra(double minCost)
throws IOException
{
setSourcePermanent();
int i=0;
int p=0;
do
{
addToPermList();
revise();
remove();
setNewPermNode();
i++;
if (currentPermIndex()>0)
{
p=currentPermIndex();
//perm[perm.length-
1].distancePortion=perm[p].distancePor
tion;
}
}while(numberOfRemainingNodes()>0
&& perm[p].distancePortion< minCost);
/*for(int j=0;j<perm.length;j++)
{
System.out.println( j+ ": "
+perm[j].distancePortion);
}*/
//--------------
class GraphOutput {
public static double
getClosedLoopCost(NodeEntry[] path)
throws IOException
{
double cost=0.0;
double totalCost=0.0;
cost=path[path.length-
1].distancePortion ;
double costBack=
Network.directLength[Network.directCol
(path[0].nodeName)][Network.directCol(
path[path.length-1].nodeName)];
totalCost=(cost +costBack);
return totalCost;
}