datavis-tech / graph-data-structure

A graph data structure with topological sort and shortest path algorithms.
MIT License
249 stars 46 forks source link

Shortest path has incorrect weight #20

Closed giraffesyo closed 6 years ago

giraffesyo commented 6 years ago

Using the following code:

var Graph = require('graph-data-structure')

var graph = Graph()

//Town A Vertices
graph.addNode('1') //a
graph.addNode('2') //b
graph.addNode('3') //c
graph.addNode('4') //d
graph.addNode('5') //e

//Town A Edges
graph.addEdge('1', '2', 2) //a -> b
graph.addEdge('2', '3', 3) //b -> c
graph.addEdge('3', '5', 5) //c -> e
graph.addEdge('5', '4', 4) //e -> d
graph.addEdge('4', '3', 4) //d -> c
graph.addEdge('5', '1', 7) //e -> a

//Town B Vertices
graph.addNode('6') //f
graph.addNode('7') //g
graph.addNode('8') //h
graph.addNode('9') //i
graph.addNode('10') //j

//Town B Edges
graph.addEdge('6', '9', 7) //f -> i
graph.addEdge('9', '10', 4) //i -> j
graph.addEdge('9', '8', 5) //i -> h
graph.addEdge('10', '6', 3) //j -> f
graph.addEdge('8', '7', 4) //h -> g
graph.addEdge('7', '6', 3) //g -> f

serializedGraph = graph.serialize()
//D to I in both ways, 3 km
graph_d_to_i = Graph(serializedGraph)
graph_d_to_i.addEdge('4', '9', 3) //d -> i
graph_d_to_i.addEdge('9', '4', 3) //i -> d

//C to J in both ways, 4km
graph_c_to_j = Graph(serializedGraph)
graph_c_to_j.addEdge('3', '10', 4) //c -> j
graph_c_to_j.addEdge('10', '3', 4) //j -> c

//I to E inb oth ways, 10km
graph_i_to_e = Graph(serializedGraph)
graph_i_to_e.addEdge('9', '5', 10) //i -> e
graph_i_to_e.addEdge('5', '9', 10) //e -> i

shortest = graph_d_to_i.shortestPath('1','10')
console.log(shortest)

The weight outputted by shortestPath() is 8, but this is incorrect.

giraffesyo commented 6 years ago

Wrote a function to add the weights up:


function calculateWeight(graph, listOfNodes) {
  let sum = 0
  for (let i = 0; i < listOfNodes.length - 1; i++) {
    console.log(`Node: ${listOfNodes[i]} Node+1: ${listOfNodes[i+1]}`)
    console.log(
      `vertex: ${listOfNodes[i]}, weight to next: ${graph.getEdgeWeight(
        listOfNodes[i],
        listOfNodes[i + 1]
      )}`
    )
    sum += parseInt(graph.getEdgeWeight(listOfNodes[i], listOfNodes[i + 1]))
  }
  return sum
}

What this showed me is that the edges were defaulting to 1... On further investigation I checked what was in the serializedGraph variable and found this:

{ nodes: 
   [ { id: 'a' },
     { id: 'b' },
     { id: 'c' },
     { id: 'e' },
     { id: 'd' },
     { id: 'f' },
     { id: 'i' },
     { id: 'g' },
     { id: 'h' },
     { id: 'j' } ],
  links: 
   [ { source: 'a', target: 'b' },
     { source: 'b', target: 'c' },
     { source: 'c', target: 'e' },
     { source: 'e', target: 'd' },
     { source: 'e', target: 'a' },
     { source: 'd', target: 'c' },
     { source: 'f', target: 'i' },
     { source: 'i', target: 'j' },
     { source: 'i', target: 'h' },
     { source: 'g', target: 'f' },
     { source: 'h', target: 'g' },
     { source: 'j', target: 'f' } ] }

As you can see, there is no weight data in the serialized graph.