Dijkstra boost distance map gives random values - boost

I am trying to solve the problem where I am given:
a graph with v vertices and e edges and the edge weights.
Output:
the weight of the minimum spanning tree
the distance between the first node(0) and the farthest node(which can be any node except 0)
Problem:
My distance map just stores a random unknown number.
My input is:
5
5 6
0 1 1
0 2 2
1 2 5
1 3 1
3 2 2
2 4 3
4 5
1 0 91
2 0 50
2 1 849
3 0 451
3 1 724
8 25
1 0 91
2 0 176
2 1 658
3 0 61
3 1 740
4 0 21
4 1 817
4 2 407
4 3 469
5 0 468
5 1 493
5 2 400
5 3 814
5 4 86
6 0 611
6 1 457
6 2 776
6 4 452
6 5 4
7 0 601
7 2 722
7 3 11
7 4 249
7 5 530
7 6 632
9 9
1 0 64
3 1 914
4 1 331
4 2 824
5 3 509
7 5 520
7 6 460
8 1 415
8 7 263
3 2
1 0 533
2 1 920
The first number is the number of testcases,then for each testcase I have the number of vertices and edges,followed by the vertice number(2 of the denoting an edge) and the respective weights.
Example:
testcases
no_vert no_edges
node_1 node_2 weight_1
node_2 node_3 weight_2
ect....
Output: is the weight of spanning tree and the distance between first and farthest node:
7 5
592 451
450 176
3386 1262
1453 1453
So instead of this correct output I get:
7 5
592 2147483647
450 2147483647
3386 2147483647
Which means there is a problem with my dijkstras approach. I am not where there is a mistake,I assume it is with the distance vector,but where?
Here is my code
//============================================================================
// Name : boost_ex_1.cpp
// Author : priya
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include<vector>
#include<algorithm>
#include<boost/graph/adjacency_list.hpp>
#include<boost/graph/prim_minimum_spanning_tree.hpp>
#include<boost/graph/dijkstra_shortest_paths.hpp>
#include<boost/graph/kruskal_min_spanning_tree.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, no_property,property<edge_weight_t, int> > Graph;
//vertex and edge descriptor
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;
int testcases();
int main() {
ios_base::sync_with_stdio(false);
int n=0;
cin>>n;
while(n--)
{
testcases();
}
return 0;
}
int testcases()
{
//creation of graphs
//get number of edges and vertices
int NEDGES,NVERT;
cin>>NVERT>>NEDGES;
//graph g
Graph g(NVERT);
Vertex SOURCE=0;
int a,b,c;
//property map for edge weights
property_map<Graph,edge_weight_t>::type weightMap = get(edge_weight,g);
//fill graph details in g
for(int i=0;i<NEDGES;++i)
{
cin >> a >> b >> c;
bool success;
Edge e;
tie(e,success) = add_edge(a,b,g);
weightMap[e]=c;
}
//filled graph with edges and vertices and weight in weightMap
vector<Edge> spanning_tree;
kruskal_minimum_spanning_tree(g,back_inserter(spanning_tree));
a=0;
for(vector<Edge>::iterator ei=spanning_tree.begin();ei!=spanning_tree.end();++ei)
{
a+=weightMap[*ei];
}
vector<int>distancep(NVERT); //distance ebtween nodes
dijkstra_shortest_paths(g,SOURCE,distance_map(&distancep[0]));
b=0;
for(int i=0;i<num_vertices(g);++i)
{
b=max(b,distancep[i]);
}
cout << a <<" "<< b << endl;
return 0;
}
I would be very grateful if anyone could help me.
Thank you.
EDIT:: In addition as you can see in my output,the last output is missing,Im also not able to figure out why.Thank you

I wanted to post the answer,In case someone has the same problem.
So, the first problem was the while loop it should be
while(n--)
NOT
while(--n)
It misses a testcase of the input.
Secondly, I had declared the grah as directedS, which is wrong,it should be undirectedS,and gave random distance values,since the values for distance was empty the otherway around.

Related

How to iterate n nested for loops each from 0 to n?

for example if n = 2
// Nested loop for all possible pairs
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// here i have to use, i, j
}
}
for example if n = 3
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
// here i have to use, i, j, k
But if n = k, then how to iterate n for loops each from 0 to n?
I tried a lot but am not able to come up with a solution.
Is there any way to do it? Please help.
Can you test it with recursive function like this :
int foo(int n, int level)
{
if(level == 0)
{
for(int i=0; i<n; i++){
//Do something
}
return someValue;
}
for(int i=0; i<n; i++){
foo(n, --level);
}
}
//Start it with level = n like this
foo(n,n);
You could use an array for the indexes.
int indexes[n] = {0}; //initialize the whole array to zero
while {
//use indexes[0..n-1] as you would i, j, k, ...
indexes[n-1]++;
//propagate carry
for(i = n-1; i > 0; i--) {
if (indexes[i] == n) {
indexes[i-1]++;
indexes[i] = 0;
}
else break; //early exit from propagation, in case it's not necessary
}
if ( indexes[0] == n) break;
}
We can use the recursive solution ( with only a single loop and rest is the power of recursion ) , you just need to specify the depth and n where:
depth which specifies the level of nested for loops you want to use
n size of each loop
Below is the c++ implementation
#include <iostream>
#include <vector>
using namespace std;
void loop(int n, int depth, vector<int> &iteration){
if(!depth){
for(auto x:iteration)
cout<<x<<" ";
cout<<endl;
return;
}
for(int i=0;i<n;i++){
iteration[iteration.size()-depth] = i;
loop(n, depth-1, iteration);
}
}
int main(int argc, char const *argv[])
{
int depth = 3, n = 5;
vector<int> iteration(depth);
loop(n, depth, iteration);
return 0;
}
Output
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
0 1 3
0 1 4
0 2 0
0 2 1
0 2 2
0 2 3
0 2 4
0 3 0
0 3 1
0 3 2
0 3 3
0 3 4
0 4 0
0 4 1
0 4 2
0 4 3
0 4 4
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 1 0
1 1 1
1 1 2
1 1 3
1 1 4
1 2 0
1 2 1
1 2 2
1 2 3
1 2 4
1 3 0
1 3 1
1 3 2
1 3 3
1 3 4
1 4 0
1 4 1
1 4 2
1 4 3
1 4 4
2 0 0
2 0 1
2 0 2
2 0 3
2 0 4
2 1 0
2 1 1
2 1 2
2 1 3
2 1 4
2 2 0
2 2 1
2 2 2
2 2 3
2 2 4
2 3 0
2 3 1
2 3 2
2 3 3
2 3 4
2 4 0
2 4 1
2 4 2
2 4 3
2 4 4
3 0 0
3 0 1
3 0 2
3 0 3
3 0 4
3 1 0
3 1 1
3 1 2
3 1 3
3 1 4
3 2 0
3 2 1
3 2 2
3 2 3
3 2 4
3 3 0
3 3 1
3 3 2
3 3 3
3 3 4
3 4 0
3 4 1
3 4 2
3 4 3
3 4 4
4 0 0
4 0 1
4 0 2
4 0 3
4 0 4
4 1 0
4 1 1
4 1 2
4 1 3
4 1 4
4 2 0
4 2 1
4 2 2
4 2 3
4 2 4
4 3 0
4 3 1
4 3 2
4 3 3
4 3 4
4 4 0
4 4 1
4 4 2
4 4 3
4 4 4
Symbolically, you are generating all values of a base-n number of n digits. You perform this by starting from all zeroes and incrementing n^n times. Every time a digit reaches them, you reset it and carry to the next.
E.g. with n=3,
000 001 002 010 011 012 020 021 022 100 101 102 110 111 112 120 121 122 200 201 202 210 211 212 220 221 222
A possible implementation is with n counters.

Algorithm for visiting all grid cells in pseudo-random order that has a guaranteed uniformity at any stage

Context:
I have a hydraulic erosion algorithm that needs to receive an array of droplet starting positions. I also already have a pattern replicating algorithm, so I only need a good pattern to replicate.
The Requirements:
I need an algorism that produces a set of n^2 entries in a set of format (x,y) or [index] that describe cells in an nxn grid (where n = 2^i where i is any positive integer).
(as a set it means that every cell is mentioned in exactly one entry)
The pattern [created by the algorism ] should contain zero to none clustering of "visited" cells at any stage.
The cell (0,0) is as close to (n-1,n-1) as to (1,1), this relates to the definition of clustering
Note
I was/am trying to find solutions through fractal-like patterns built through recursion, but at the time of writing this, my solution is a lookup table of a checkerboard pattern(list of black cells + list of white cells) (which is bad, but yields fewer artifacts than an ordered list)
C, C++, C#, Java implementations (if any) are preferred
You can use a linear congruential generator to create an even distribution across your n×n space. For example, if you have a 64×64 grid, using a stride of 47 will create the pattern on the left below. (Run on jsbin) The cells are visited from light to dark.
That pattern does not cluster, but it is rather uniform. It uses a simple row-wide transformation where
k = (k + 47) mod (n * n)
x = k mod n
y = k div n
You can add a bit of randomness by making k the index of a space-filling curve such as the Hilbert curve. This will yield the pattern on the right. (Run on jsbin)
     
     
You can see the code in the jsbin links.
I have solved the problem myself and just sharing my solution:
here are my outputs for the i between 0 and 3:
power: 0
ordering:
0
matrix visit order:
0
power: 1
ordering:
0 3 2 1
matrix visit order:
0 3
2 1
power: 2
ordering:
0 10 8 2 5 15 13 7 4 14 12 6 1 11 9 3
matrix visit order:
0 12 3 15
8 4 11 7
2 14 1 13
10 6 9 5
power: 3
ordering:
0 36 32 4 18 54 50 22 16 52 48 20 2 38 34 6
9 45 41 13 27 63 59 31 25 61 57 29 11 47 43 15
8 44 40 12 26 62 58 30 24 60 56 28 10 46 42 14
1 37 33 5 19 55 51 23 17 53 49 21 3 39 35 7
matrix visit order:
0 48 12 60 3 51 15 63
32 16 44 28 35 19 47 31
8 56 4 52 11 59 7 55
40 24 36 20 43 27 39 23
2 50 14 62 1 49 13 61
34 18 46 30 33 17 45 29
10 58 6 54 9 57 5 53
42 26 38 22 41 25 37 21
the code:
public static int[] GetPattern(int power, int maxReturnSize = int.MaxValue)
{
int sideLength = 1 << power;
int cellsNumber = sideLength * sideLength;
int[] ret = new int[cellsNumber];
for ( int i = 0 ; i < cellsNumber && i < maxReturnSize ; i++ ) {
// this loop's body can be used for per-request computation
int x = 0;
int y = 0;
for ( int p = power - 1 ; p >= 0 ; p-- ) {
int temp = (i >> (p * 2)) % 4; //2 bits of the index starting from the begining
int a = temp % 2; // the first bit
int b = temp >> 1; // the second bit
x += a << power - 1 - p;
y += (a ^ b) << power - 1 - p;// ^ is XOR
// 00=>(0,0), 01 =>(1,1) 10 =>(0,1) 11 =>(1,0) scaled to 2^p where 0<=p
}
//to index
int index = y * sideLength + x;
ret[i] = index;
}
return ret;
}
I do admit that somewhere along the way the values got transposed, but it does not matter because of how it works.
After doing some optimization I came up with this loop body:
int x = 0;
int y = 0;
for ( int p = 0 ; p < power ; p++ ) {
int temp = ( i >> ( p * 2 ) ) & 3;
int a = temp & 1;
int b = temp >> 1;
x = ( x << 1 ) | a;
y = ( y << 1 ) | ( a ^ b );
}
int index = y * sideLength + x;
(the code assumes that c# optimizer, IL2CPP, and CPP compiler will optimize variables temp, a, b out)

How to make a N×N matrix each of i-th row and i-th column having all the elements 1 to 2N-1?

This question was asked as a puzzle in one Book of Puzzles by RS AGGARWAL, which stated the problem as to build an order N matrix where each i'th row and i'th column combined have all the elements from 1 to 2N-1.
For instance, for N=2
[3,2]
[1,3]
I want to know when is an answer possible for it for which values of N it is possible to make a matrix and how to make it? and write code for it
this has simple solution for square matrices where n is power of 2 so n=1,2,4,8,16,... do not ask me why there surely is some math proof for it ...
The algorithm to create such matrix is easy:
clear matrix (with 0)
loop i through all values i=1,2,3...2n-1
for each i find all locations where i matrix is not yet filled (0) and there is not i present in row and column
fill the position with i and repeat until no such location found.
In C++ something like this:
//---------------------------------------------------------------------------
const int n=8;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init(int m[n][n])
{
int i,x,y,h[n][n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// clear histograms
for (i=0;i<n;i++) hist_rst(h[i]);
// try to fill values 1..2n-1
for (i=1;i<n+n;i++)
{
// find free position
for (x=0;x<n;x++) if (!h[x][i])
for (y=0;y<n;y++) if (!h[y][i])
if (!m[x][y])
{
// set cell
m[x][y]=i;
h[x][i]=1;
h[y][i]=1;
break;
}
}
}
//---------------------------------------------------------------------------
here few outputs:
1
1 3
2 1
1 5 6 7
2 1 7 6
3 4 1 5
4 3 2 1
1 9 10 11 12 13 14 15
2 1 11 10 13 12 15 14
3 4 1 9 14 15 12 13
4 3 2 1 15 14 13 12
5 6 7 8 1 9 10 11
6 5 8 7 2 1 11 10
7 8 5 6 3 4 1 9
8 7 6 5 4 3 2 1
for non power of 2 matrices you could use backtracking but take in mind even 4x4 matrix will have many iterations to check ... so some heuristics would need to be in place to make it possible in finite time... as brute force is (n+n)^(n*n) so for n=4 there are 281474976710656 combinations to check ...
[edit1] genere&test solution for even n
//---------------------------------------------------------------------------
const int n=6;
int m[n][n];
//---------------------------------------------------------------------------
// compute histogram u[n+n] of values per ith row,col of m[n][n]
void hist_rst(int *u ) { for (int j=0;j<n+n;j++) u[j]=0; }
void hist_row(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[j][i]]=1; }
void hist_col(int *u,int m[n][n],int i) { for (int j=0;j<n;j++) u[m[i][j]]=1; }
//---------------------------------------------------------------------------
void matrix_init2(int m[n][n]) // brute force
{
int x,y,a,ax[(n*n)>>1],ay[(n*n)>>1],an,u[n+n];
// clear matrix (unused cells)
for (x=0;x<n;x++)
for (y=0;y<n;y++)
m[x][y]=0;
// main diagonal 1,1,1,1...
for (x=0;x<n;x++) m[x][x]=1;
// 1st row 1,2,3...n
for (x=1;x<n;x++) m[x][0]=x+1;
// cells for brute force
for (an=0,x=0;x<n;x++)
for (y=0;y<x;y++)
if (!m[x][y])
{
ax[an]=x;
ay[an]=y;
an++;
m[x][y]=2;
}
// brute force attack values 2,3,4,5,...,n-1
for (;;)
{
// increment solution
for (a=0;a<an;a++)
{
x=ax[a];
y=ay[a];
m[x][y]++;
if (m[x][y]<=n) break;
m[x][y]=2;
}
if (a>=an) break; // no solution
// test
for (x=0;x<n;x++)
{
hist_rst(u);
hist_col(u,m,x);
hist_row(u,m,x);
for (y=1;y<=n;y++) if (!u[y]) { y=0; x=n; break; }
}
if (y) break; // solution found
}
// mirror other triangle
for (x=0;x<n;x++)
for (y=0;y<x;y++)
m[y][x]=m[x][y]+n-1;
}
//---------------------------------------------------------------------------
however its slow so do not try to go with n>6 without more optimizations/better heuristics... for now it is using triangle+mirror and diagonal + first row hard-coded heuristics.
maybe somehow exploit the fact that each iterated value will be placed n/2 times could speed this up more but too lazy to implement it ...
Here output for n=6:
[ 52.609 ms]
1 2 3 4 5 6
7 1 6 5 3 4
8 11 1 2 4 5
9 10 7 1 6 3
10 8 9 11 1 2
11 9 10 8 7 1
iterating through 5^10 cases ...
As requested by Spektre, here is the 6x6 matrix.
I an interesting property that may be used as heuristic. We need only to solve a triangular matrix because the other half can be easily deduced. We fill the upper (or lower) half of the matrix by values from 1 to n only. We can then complete the matrix by using the property that a[j][i] = 2n + 1 - a[i][j].
Another property I found is that there is a trivial way to place 1, 2 and N in the matrix. The values 1 are all on the diagonal, the values 2 and N are next to the diagonal at a step 2.
Finally, another thing I found is that matrix with odd N have no solutions. It is because the value in a[i][j] belongs to row and column i and row and column j. We thus need an even number of row and columns to store all values.
Here is the 6x6 matrix I found manually.
1 2 3 4 5 6
11 1 6 5 3 4
10 7 1 2 4 5
9 8 11 1 6 3
8 10 9 7 1 2
7 9 8 10 11 1
As we can see 2 + 11 = 6 + 7 = 3 + 10 = 13 = 2*6+1.
Here is a 4x4 matrix
1 2 3 4
7 1 4 3
6 5 1 2
5 6 7 1
Here again 2 + 7 = 4 + 5 = 3 + 6 = 9 = 2*4+1
It is possible to have other permutations of values >N, but with the 2N+1 property we can trivially deduce one triangular matrix from the other.
EDIT
Here is a solution for power two sized matrix. The matrix of size 2048x2048 is generated in 57ms (without printing).
#include <stdio.h>
int **newMatrix(int n) {
int **m = calloc(n, sizeof(int*));
m[0] = calloc(n*n, sizeof(int));
for (int i = 1; i < n; i++)
m[i] = m[0]+i*n;
return m;
}
void printMatrix(int **m, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%3d ", m[i][j]);
printf("\n");
}
}
void fillPowerTwoMatrix(int **m, int n) {
// return if n is not power two
if (n < 0 || n&(n-1) != 0)
return;
for (int i = 0; i < n; i++)
m[0][i] = i+1;
for (int w = 1; w < n; w *= 2)
for (int k = 0; k < n; k += 2*w)
for (int i = 0; i < w; i++)
for (int j = k; j < k+w; j++) {
m[i+w][j] = m[i][j+w];
m[i+w][j+w] = m[i][j];
}
int k = 2*n+1;
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
m[i][j] = k - m[j][i];
}
int main() {
int n = 16;
int **m = newMatrix(n);
fillPowerTwoMatrix(m, n);
printMatrix(m, n);
return 0;
}
Here is the matrix 16x16. As can be seen there is a symmetry that is exploited to efficiently generate the matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
31 1 4 3 6 5 8 7 10 9 12 11 14 13 16 15
30 29 1 2 7 8 5 6 11 12 9 10 15 16 13 14
29 30 31 1 8 7 6 5 12 11 10 9 16 15 14 13
28 27 26 25 1 2 3 4 13 14 15 16 9 10 11 12
27 28 25 26 31 1 4 3 14 13 16 15 10 9 12 11
26 25 28 27 30 29 1 2 15 16 13 14 11 12 9 10
25 26 27 28 29 30 31 1 16 15 14 13 12 11 10 9
24 23 22 21 20 19 18 17 1 2 3 4 5 6 7 8
23 24 21 22 19 20 17 18 31 1 4 3 6 5 8 7
22 21 24 23 18 17 20 19 30 29 1 2 7 8 5 6
21 22 23 24 17 18 19 20 29 30 31 1 8 7 6 5
20 19 18 17 24 23 22 21 28 27 26 25 1 2 3 4
19 20 17 18 23 24 21 22 27 28 25 26 31 1 4 3
18 17 20 19 22 21 24 23 26 25 28 27 30 29 1 2
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1

How does recursion of Quick sort work?

The functions below are an implementation of Quick sort. Here we take the last element as a pivot.
I understood the partition function(where the pivot comes to its sorted position) but I can't understand the recursive function qs. The function qs calls itself recursively to solve the left side by qs(a,start,pi-1) and the right of the partition by qs(a,pi+1,end).
Does it the solve the left and then the (left of the left) then (the left of(the left of the left), etc, and then left, left...right, etc. Or does it alternate by solving the left side and then right side.
PS: I want to know whats happening inside the computer, the mechanism of this recursion of quick sort. The program is working but I want to know how it works.
int partition(int *a, int start, int end)
{
int pivot=a[end];
int pi=start;
for(int i=start; i<end; i++)
{
if(a[i]<=pivot)
{
swap(a[i],a[pi]);
pi++;
}
}
swap(a[pi], a[end]);
return pi;
}
void qs(int*a, int start, int end)
{
if(start<end)
{
int pi=partition(a,start,end);
qs(a,start,pi-1);
qs(a,pi+1,end);
}
}
Example of the order of operations for Lomuto partition scheme, where pivot = array[high].
quicksort(array, low, pivot-1), quicksort(array, pivot+1, high).
A vertical bar used to show left sub-array, pivot, right sub-array.
11 13 14 12 10 8 9 5 6 4 2 0 1 3 7
5 6 4 2 0 1 3 11 13 14 12 10 8 9 7
5 6 4 2 0 1 3| 7|13 14 12 10 8 9 11
2 0 1 5 6 4 3
2 0 1| 3| 6 4 5
0 2 1
0| 1| 2
4 6 5
4| 5| 6
10 8 9 13 14 12 11
10 8 9|11|14 12 13
8 10 9
8| 9|10
12 14 13
12|13|14
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
The best way for understanding the order in which things are happening that I can suggest you, is by printing some debugging info in your qs method. To achieve that, I would add an additional argument by ref, in which I would count the number of times the qs function is called, and print that info next to the bounds of the partition being solved. e.g.
void qs(int*a, int start, int end, int &stepCount)
{
if(start<end)
{
int currentStep = stepCount++;
cout << "Solving step " << currentStep << " partition from " << start << " to " << end << endl;
int pi=partition(a,start,end);
qs(a,start,pi-1,stepCount);
qs(a,pi+1,end,stepCount);
cout << "Finished solving step " << currentStep << endl;
}
}
Don't understand your PS question. It's very broad. You mean specifically in the partitioning? In how recursion is handled? How the bits move around in memory?

Travelling Sales Man (need to visit only subset of nodes): Bugged

I need help with my travelling sales man problem code. Its bugged... I know because its a school assignment and there are test cases. So here it goes.
Given a connected graph where I need to visit a subset of nodes. How do I compute the shortest path?
As an example, refer to above image. I need to start from 0 and visit some/all nodes then go back to zero. In the process, I need to compute the shortest path.
Suppose I need to visit all nodes, I will go from 0 -> 1 -> 2 -> 3 -> 0 = 20 + 30 + 12 + 35 = 97. Suppose now I only need to visit node 2, I will go from 0 -> 3 -> 2 -> 3 -> 0 as that gives shortest path of 94 (I can visit nodes I don't have to visit if it can give a shortest path).
Basically, I did:
Compute shortest path between any 2 pairs of required nodes and the source (0). This gives me a shortest path 2D table like (I used dijkstra's):
| 0 1 2 3
--+--------------
0 |
1 |
2 |
3 |
Now, I modify the shopping sales man algorithm (aka. Floyd Warshall’s or APSP) to use this table. Current Java source (TSP and dijkstra's) looks like:
int TSP(int source, int visited) {
if (visited == (int)(Math.pow(2, K)-1)) { // all required visited
return sssp.get(source).get(0); // return to source (0)
} else if (memo.containsKey(source) && memo.get(source).containsKey(visited)) {
return memo.get(source).get(visited);
} else {
int item;
if (!memo.containsKey(source)) {
memo.put(source, new HashMap<Integer, Integer>());
}
memo.get(source).put(visited, 1000000);
for (int v = 0; v < K; v++) {
item = shoppingList[v];
if (!hasVisited(visited, item)) {
memo.get(source).put(visited, Math.min(
memo.get(source).get(visited),
sssp.get(source).get(item) + TSP(item, visit(visited, v))
));
}
}
return memo.get(source).get(visited);
}
}
int dijkstra(int src, int dest) {
PriorityQueue<IntegerPair> PQ = new PriorityQueue<IntegerPair>();
HashMap<Integer, Integer> dist = new HashMap<Integer, Integer>(); // shortest known dist from {src} to {node}
// init shortest known distance
for (int i = 0; i < N+1; i++) {
if (i != src) {
dist.put(i, Integer.MAX_VALUE); // dist to any {i} is big(unknown) by default
} else {
dist.put(src, 0); // dist to {src} is always 0
}
}
IntegerPair node;
int nodeDist;
int nodeIndex;
PQ.offer(new IntegerPair(0, src));
while (PQ.size() > 0) {
node = PQ.poll();
nodeDist = node.first();
nodeIndex = node.second();
if (nodeDist == dist.get(nodeIndex)) {
// process out going edges
for (int v = 0; v < N+1; v++) { // since its a complete graph, process all edges
if (v != nodeIndex) { // except curr node
if (dist.get(v) > dist.get(nodeIndex) + T[nodeIndex][v]) { // relax if possible
dist.put(v, dist.get(nodeIndex) + T[nodeIndex][v]);
PQ.offer(new IntegerPair(dist.get(v), v));
}
}
}
}
}
return dist.get(dest);
}
visited is used as a bitmask to indicate if a node has been visited
sssp is a HashMap<Integer, HashMap<Integer, Integer>> where the 1st hashmap's key is the source node and the key for 2nd hashmap is the destination. So it basically represent the 2D table u see in point 1.
memo is just what I used in dynamic programming as a "cache" of previously computed shortest path from a node, given a visited bitmap.
Full source: http://pastie.org/5171509
The test case that passes:
1
3 3
1 2 3
0 20 51 35
20 0 30 34
51 30 0 12
35 34 12 0
Where 1st line is the number of test cases. 3rd line (3 3). The 1st 3 is the number of nodes, 2nd 3 is the number of required nodes. 4th line is the list of required nodes. Then the rest is the table of edge weights.
The test case that fails is:
9 9
1 2 3 4 5 6 7 8 9
0 42 360 335 188 170 725 479 359 206
42 0 402 377 146 212 767 521 401 248
360 402 0 573 548 190 392 488 490 154
335 377 573 0 293 383 422 717 683 419
188 146 548 293 0 358 715 667 539 394
170 212 190 383 358 0 582 370 300 36
725 767 392 422 715 582 0 880 704 546
479 521 488 717 667 370 880 0 323 334
359 401 490 683 539 300 704 323 0 336
206 248 154 419 394 36 546 334 336 0
I got 3995 but the answer is 2537... sorry I know this is hard to debug ... I am having the same problem, the test case is too large ... at least for humans ... so I am creating smaller test case to test but they seem to pass ...
Perhaps not a full answer but I think it's at least pointing in the right direction: your code seems to give the results of following the paths 0->1->2->...->N->0. No real optimization seems to happen.
I reworked your code a bit to get a small failing test case:
int[][]mat=new int[N+1][N+1];
//original
//mat[0]=new int[]{0,20,51,35};
//mat[1]=new int[]{20,0,30,34};
//mat[2]=new int[]{51,30,0,12};
//mat[3]=new int[]{35,34,12,0};
//switched order of nodes, node 2 is now node 1
mat[0]=new int[]{0,51,20,35};
mat[1]=new int[]{51,0,30,12};
mat[2]=new int[]{20,30,0,34};
mat[3]=new int[]{35,12,34,0};
This produces 146 as a best path, showing that it follows the path 0->1->2->3->0 (47+30+34+35, 47 is the shortest path 0 to 1 using node 4) (all node numbers are with my order switch).
edit: I found the culprit after another quick look. You have the line if (!hasVisited(visited, item)) to check if you already visited node item. However, visited is built up by visit(visited, v), in which v is an index into the shoppinglist. item =shoppinglist[v] but you should use the same if you're shifting your visited vector.
You should use if (!hasVisited(visited, v)) instead of if (!hasVisited(visited, item))
On an unrelated note, I'm unsure if the first step of finding the shortest paths is necessary or could influence your results. If a direct link from A to B is longer than going through other nodes (say C), then it is replaced in the distance table. If you would then use that link in your final solution to go from A to B, then you would actually be going via C, which would already be in your path (since that path is a full TSP solution). If a node can only be visited once, then this might be a problem.

Resources