github.com/LdDl/ch@v1.7.8/dijkstra_local.go (about)

     1  package ch
     2  
     3  const (
     4  	Infinity = float64(^uint(0) >> 1)
     5  	// Infinity = Infinity
     6  )
     7  
     8  // shortestPathsWithMaxCost Internal implementation of Dijkstra's algorithm to compute witness paths
     9  func (graph *Graph) shortestPathsWithMaxCost(source int64, maxcost float64, previousOrderPos int64) {
    10  	// Heap to store traveled distance
    11  	pqComparator := &distanceHeap{}
    12  	pqComparator.Push(&graph.Vertices[source])
    13  
    14  	// Instead of inializing distances to Infinity every single shortestPathsWithMaxCost(...) call we can do following
    15  	// Set dist[source] -> 0 (as usual)
    16  	graph.Vertices[source].distance.distance = 0
    17  	// Set order position to previously contracted (excluded from graph) vertex
    18  	graph.Vertices[source].distance.previousOrderPos = previousOrderPos
    19  	// Set source to identifier of vertex for which shortestPathsWithMaxCost(...) has been called
    20  	graph.Vertices[source].distance.previousSourceID = source
    21  
    22  	for pqComparator.Len() != 0 {
    23  		vertex := pqComparator.Pop()
    24  		// Do not consider any vertex has been excluded earlier
    25  		if vertex.contracted {
    26  			continue
    27  		}
    28  		// Once a vertex is settled with a shortest path score greater than max cost, search stops.
    29  		if vertex.distance.distance > maxcost {
    30  			return
    31  		}
    32  		// Edge relaxation
    33  		vertexList := vertex.outIncidentEdges
    34  		for i := range vertexList {
    35  			temp := vertexList[i].vertexID
    36  			cost := vertexList[i].weight
    37  			tempPtr := &graph.Vertices[temp]
    38  			// Do not consider any vertex has been excluded earlier
    39  			if tempPtr.contracted {
    40  				continue
    41  			}
    42  			alt := vertex.distance.distance + cost
    43  			if tempPtr.distance.distance > alt || // usual condition for Dijkstra's algorithm
    44  				vertex.distance.previousOrderPos != tempPtr.distance.previousOrderPos || // Optional condition: if previous shortestPathsWithMaxCost(...) call has changed shortest path tree
    45  				vertex.distance.previousSourceID != tempPtr.distance.previousSourceID { // Optional condition: if previous shortestPathsWithMaxCost(...) call has changed shortest path tree
    46  				// Update new shortest distance
    47  				tempPtr.distance.distance = vertex.distance.distance + cost
    48  				tempPtr.distance.previousOrderPos = previousOrderPos
    49  				tempPtr.distance.previousSourceID = source
    50  				pqComparator.Push(tempPtr)
    51  			}
    52  		}
    53  	}
    54  }