public void testGrowReplaceShrink() { Random r = new Random(); int k = 10000; String s = "A"; double t = 0; FibonacciHeap<String> h = new FibonacciHeap<>(); for (int i = 0; i < (k * 3); ++i) { // during first two-thirds, insert if (i < (k * 2)) { double d = r.nextDouble(); t += d; FibonacciHeapNode<String> n = new FibonacciHeapNode<>(s); h.insert(n, d); } // during last two-thirds, delete (so during middle // third, we'll do both insert and delete, interleaved) if (i >= k) { FibonacciHeapNode<String> n2 = h.removeMin(); t -= n2.getKey(); } } assertTrue(h.isEmpty()); // tally should come back down to zero, or thereabouts (due to roundoff) assertEquals(0.0, t, 0.00001); }
// makes x's nextSibling and prevSibling point to itself private void removeFromSiblings(FibonacciHeapNode x) { if (x.nextSibling == x) return; x.nextSibling.prevSibling = x.prevSibling; x.prevSibling.nextSibling = x.nextSibling; x.nextSibling = x; x.prevSibling = x; }
// joins siblings lists of a and b private void concatenateSiblings(FibonacciHeapNode a, FibonacciHeapNode b) { a.nextSibling.prevSibling = b; b.nextSibling.prevSibling = a; FibonacciHeapNode origAnext = a.nextSibling; a.nextSibling = b.nextSibling; b.nextSibling = origAnext; }
// links y under x private void link(FibonacciHeapNode y, FibonacciHeapNode x) { removeFromSiblings(y); y.parent = x; if (x.child == null) x.child = y; else concatenateSiblings(x.child, y); x.degree++; y.mark = false; }
// in honor of sf.net bug #1845376 public void testAddRemoveOne() { String s = "A"; FibonacciHeapNode<String> n = new FibonacciHeapNode<>(s); FibonacciHeap<String> h = new FibonacciHeap<>(); assertTrue(h.isEmpty()); h.insert(n, 1.0); assertFalse(h.isEmpty()); FibonacciHeapNode<String> n2 = h.removeMin(); assertEquals(s, n2.getData()); assertTrue(h.isEmpty()); }
// cut node x from below y private void cut(FibonacciHeapNode x, FibonacciHeapNode y) { // remove x from y's children if (y.child == x) y.child = x.nextSibling; if (y.child == x) y.child = null; y.degree--; removeFromSiblings(x); concatenateSiblings(x, min); x.parent = null; x.mark = false; }
/** * Decreases the <code>priority</code> value associated with * <code>item</code>. * * <p> * * <code>item<code> must exist in the heap, and it's current * priority must be greater than <code>priority</code>. * * @throws IllegalStateException if <code>item</code> does not exist * in the heap, or if <code>item</code> already has an equal or * lower priority than the supplied<code>priority</code>. */ public void decreaseKey(Object item, int priority) { FibonacciHeapNode node = (FibonacciHeapNode) itemsToNodes.get(item); if (node == null) throw new IllegalStateException("No such element: " + item); if (node.priority < priority) throw new IllegalStateException( "decreaseKey(" + item + ", " + priority + ") called, but priority=" + node.priority); node.priority = priority; FibonacciHeapNode parent = node.parent; if ((parent != null) && (node.priority < parent.priority)) { cut(node, parent); cascadingCut(parent); } if (node.priority < min.priority) min = node; }
private void cascadingCut(FibonacciHeapNode y) { FibonacciHeapNode z = y.parent; if (z != null) { if (!y.mark) { y.mark = true; } else { cut(y, z); cascadingCut(z); } } }
/** * Returns the object which has the <em>lowest</em> priority in the heap. If the heap is empty, * <code>null</code> is returned. */ public Object popMin() { if (min == null) return null; if (min.child != null) { FibonacciHeapNode tmp = min.child; // rempve parent pointers to min while (tmp.parent != null) { tmp.parent = null; tmp = tmp.nextSibling; } // add children of min to root list concatenateSiblings(tmp, min); } // remove min from root list FibonacciHeapNode oldMin = min; if (min.nextSibling == min) { min = null; } else { min = min.nextSibling; removeFromSiblings(oldMin); consolidate(); } itemsToNodes.remove(oldMin.userObject); return oldMin.userObject; }
/** * routing using A* algorithm with fibonacci heap basically same as routingAStar function * * @param startNode * @param endNode * @param startTime * @param pathNodeList return path * @return */ public static double routingAStarFibonacci( long startNode, long endNode, int startTime, int dayIndex, ArrayList<Long> pathNodeList) { System.out.println("start finding the path..."); int debug = 0; double totalCost = -1; try { // test store transversal nodes // HashSet<Long> transversalSet = new HashSet<Long>(); if (!OSMData.nodeHashMap.containsKey(startNode) || !OSMData.nodeHashMap.containsKey(endNode)) { System.err.println("cannot find start or end node!"); return -1; } if (startNode == endNode) { System.out.println("start node is the same as end node."); return 0; } HashSet<Long> closedSet = new HashSet<Long>(); HashMap<Long, FibonacciHeapNode<NodeInfoHelper>> nodeHelperCache = new HashMap<Long, FibonacciHeapNode<NodeInfoHelper>>(); FibonacciHeap<NodeInfoHelper> openSet = initialStartSet(startNode, endNode, nodeHelperCache); HashSet<Long> endSet = initialEndSet(endNode); NodeInfoHelper current = null; FibonacciHeapNode<NodeInfoHelper> fCurrent = null; while (!openSet.isEmpty()) { // remove current from openset fCurrent = openSet.min(); openSet.removeMin(); current = fCurrent.getData(); // if(!transversalSet.contains(current.getNodeId())) // transversalSet.add(current.getNodeId()); long nodeId = current.getNodeId(); // add current to closedset closedSet.add(nodeId); if (endSet.contains(nodeId)) { // find the destination current = current.getEndNodeHelper(endNode); totalCost = current.getCost(); break; } // for time dependent routing int timeIndex = startTime + (int) (current.getCost() / OSMParam.SECOND_PER_MINUTE / OSMRouteParam.TIME_INTERVAL); if (timeIndex > OSMRouteParam.TIME_RANGE - 1) // time [6am - 9 pm], we regard times after 9pm as constant edge weights timeIndex = OSMRouteParam.TIME_RANGE - 1; LinkedList<ToNodeInfo> adjNodeList = OSMData.adjListHashMap.get(nodeId); if (adjNodeList == null) continue; // this node cannot go anywhere double arriveTime = current.getCost(); // for each neighbor in neighbor_nodes(current) for (ToNodeInfo toNode : adjNodeList) { debug++; long toNodeId = toNode.getNodeId(); int travelTime; if (toNode.isFix()) // fix time travelTime = toNode.getTravelTime(); else // fetch from time array travelTime = toNode.getSpecificTravelTime(dayIndex, timeIndex); // tentative_g_score := g_score[current] + dist_between(current,neighbor) double costTime = arriveTime + (double) travelTime / OSMParam.MILLI_PER_SECOND; // tentative_f_score := tentative_g_score + heuristic_cost_estimate(neighbor, goal) double heuristicTime = estimateHeuristic(toNodeId, endNode); double totalCostTime = costTime + heuristicTime; // if neighbor in closedset and tentative_f_score >= f_score[neighbor] if (closedSet.contains(toNodeId) && nodeHelperCache.get(toNodeId).getData().getTotalCost() <= totalCostTime) { continue; } NodeInfoHelper node = null; FibonacciHeapNode<NodeInfoHelper> fNode = null; // if neighbor not in openset or tentative_f_score < f_score[neighbor] if (!nodeHelperCache.containsKey(toNodeId)) { // neighbor not in openset // create new one node = new NodeInfoHelper(toNodeId); node.setCost(costTime); node.setHeuristic(heuristicTime); node.setParentId(nodeId); fNode = new FibonacciHeapNode<NodeInfoHelper>(node); openSet.insert(fNode, node.getTotalCost()); nodeHelperCache.put(node.getNodeId(), fNode); } else if (nodeHelperCache.get(toNodeId).getData().getTotalCost() > totalCostTime) { // neighbor in openset fNode = nodeHelperCache.get(toNodeId); node = fNode.getData(); // update information node.setCost(costTime); node.setHeuristic(heuristicTime); node.setParentId(nodeId); if (closedSet.contains(toNodeId)) { // neighbor in closeset closedSet.remove(toNodeId); // remove neighbor form colseset openSet.insert(fNode, node.getTotalCost()); } else { // neighbor in openset, decreaseKey openSet.decreaseKey(fNode, node.getTotalCost()); } } } } if (totalCost != -1) { long traceNodeId = current.getNodeId(); pathNodeList.add(traceNodeId); // add end node traceNodeId = current.getParentId(); while (traceNodeId != 0) { pathNodeList.add(traceNodeId); // add node fCurrent = nodeHelperCache.get(traceNodeId); current = fCurrent.getData(); traceNodeId = current.getParentId(); } Collections.reverse(pathNodeList); // reverse the path list System.out.println("find the path successful!"); } else { System.out.println("can not find the path!"); } // OSMOutput.generateTransversalNodeKML(transversalSet, nodeHashMap); } catch (Exception e) { e.printStackTrace(); System.err.println( "tdsp: debug code " + debug + ", start node " + startNode + ", end node " + endNode); } return totalCost; }