Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV4.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV4.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV4.cs	(revision 8527)
@@ -0,0 +1,143 @@
+﻿
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.GraphRouting.Interfaces;
+using HeuristicLab.Problems.RoutePlanning.Interfaces;
+using HeuristicLab.Problems.RoutePlanning.RoutingGraph;
+namespace HeuristicLab.Algorithms.GraphRouting {
+  public class AStarAlgorithmV4 : IRouter {
+    private IGraph graph;
+    private ICostCalculator costCalculator;
+
+    private Dictionary<long, float> distances;
+    private Dictionary<long, long> predecessors;
+    private List<long> closedList;
+    private HashSet<long> closedListLookup;
+    private SortedSet<NodeData> openList;
+    private Dictionary<long, NodeData> openListLookup;
+
+    public AStarAlgorithmV4(IGraph graph)
+      : this(graph, new TravelTimeCostCalculator()) {
+    }
+
+    public AStarAlgorithmV4(IGraph graph, ICostCalculator costCalc) {
+      this.graph = graph;
+      this.costCalculator = costCalc;
+    }
+
+    #region IRouter Members
+
+    public long[] Calculate(long sourceNodeId, long targetNodeId) {
+      distances = new Dictionary<long, float>();
+      predecessors = new Dictionary<long, long>();
+      closedList = new List<long>();
+      closedListLookup = new HashSet<long>();
+      openList = new SortedSet<NodeData>();
+      openListLookup = new Dictionary<long, NodeData>();
+
+      long currentNode = sourceNodeId;
+
+      NodeData nd = new NodeData(currentNode, 0);
+      openList.Add(nd);
+      openListLookup.Add(currentNode, nd);
+      distances.Add(currentNode, 0);
+
+      while (openList.Count > 0) {
+        NodeData data = openList.Min;
+        openList.Remove(data);
+        openListLookup.Remove(data.Node);
+        currentNode = data.Node;
+        if (currentNode == targetNodeId) {
+          return ReconstructPath(currentNode).ToArray();
+        }
+
+        //--------------
+        //Logger.LogToFile("cn = " + currentNode + " (" + data.Costs + ")");
+        //--------------
+
+        Dictionary<long, float> currentNeighbors = graph.GetNeighborsWithWeight(currentNode);
+        foreach (KeyValuePair<long, float> neighbor in currentNeighbors) {
+          if (closedListLookup.Contains(neighbor.Key))
+            continue;
+
+          float costsFromStart = GetDistance(currentNode) + neighbor.Value;
+
+          if (openListLookup.ContainsKey(neighbor.Key) && costsFromStart > GetDistance(neighbor.Key))
+            continue;
+
+          distances[neighbor.Key] = costsFromStart;
+          predecessors[neighbor.Key] = currentNode;
+
+          Vertex vertNeigh = graph.GetVertex(neighbor.Key);
+          Vertex vertTarget = graph.GetVertex(targetNodeId);
+          float f = costsFromStart + costCalculator.EstimatedCosts(vertNeigh, vertTarget);
+
+          //--------------
+          //Logger.LogToFile("    neigb:" + neighbor.Key + " (" + costsFromStart + " / " + f + ")");
+          //--------------
+
+          if (openListLookup.ContainsKey(neighbor.Key)) {
+            openList.Remove(openListLookup[neighbor.Key]);
+            openListLookup.Remove(neighbor.Key);
+          }
+
+          NodeData newNode = new NodeData(neighbor.Key, f);
+          while (!openList.Add(newNode)) {
+            newNode.Costs = newNode.Costs + 0.0000001f;
+          }
+          openListLookup.Add(newNode.Node, newNode);
+        }
+        closedList.Add(currentNode);
+        closedListLookup.Add(currentNode);
+        //--------------
+        //Logger.LogToFile("");
+        //--------------
+      }
+      throw new Exception(string.Format("No route found from {0} to {1}", sourceNodeId, targetNodeId));
+    }
+
+    #endregion
+
+    private float GetDistance(long id) {
+      float d;
+      if (distances.TryGetValue(id, out d)) {
+        return d;
+      } else { return float.MaxValue; }
+    }
+
+    private List<long> ReconstructPath(long nodeId) {
+      List<long> route = new List<long>();
+      long current = nodeId;
+      long next;
+
+      if (!predecessors.TryGetValue(current, out next)) {
+        return null;
+      }
+      route.Add(current);
+      while (predecessors.TryGetValue(current, out next)) {
+        current = predecessors[current];
+        route.Add(current);
+      }
+      route.Reverse();
+      return route;
+    }
+
+    private class NodeData : IComparable<NodeData> {
+      public long Node { get; set; }
+      public float Costs { get; set; }
+
+      public NodeData(long nodeId, float f) {
+        Node = nodeId;
+        Costs = f;
+      }
+
+      #region IComparable<NodeData> Members
+
+      public int CompareTo(NodeData other) {
+        return this.Costs > other.Costs ? 1 : this.Costs < other.Costs ? -1 : 0;
+      }
+
+      #endregion
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV5.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV5.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/AStarAlgorithmV5.cs	(revision 8527)
@@ -0,0 +1,136 @@
+﻿
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.GraphRouting.Interfaces;
+using HeuristicLab.Algorithms.GraphRouting.PriorityQueues;
+using HeuristicLab.Problems.RoutePlanning.Interfaces;
+using HeuristicLab.Problems.RoutePlanning.RoutingGraph;
+namespace HeuristicLab.Algorithms.GraphRouting {
+  public class AStarAlgorithmV5 : IRouter {
+    private IGraph graph;
+    private ICostCalculator costCalculator;
+
+    private Dictionary<long, float> distances;
+    private Dictionary<long, long> predecessors;
+    private List<long> closedList;
+    private HashSet<long> closedListLookup;
+
+    private HashSet<long> openListLookup;
+    private IHeap<float, long> openList;
+
+    public AStarAlgorithmV5(IGraph graph)
+      : this(graph, new TravelTimeCostCalculator()) {
+    }
+
+    public AStarAlgorithmV5(IGraph graph, ICostCalculator costCalc) {
+      this.graph = graph;
+      this.costCalculator = costCalc;
+    }
+
+    #region IRouter Members
+
+    public long[] Calculate(long sourceNodeId, long targetNodeId) {
+      distances = new Dictionary<long, float>();
+      predecessors = new Dictionary<long, long>();
+
+      closedList = new List<long>();
+      closedListLookup = new HashSet<long>();
+
+      //openList = new BinHeap<float, long>(300000);
+      openList = new BinomialHeap<float, long>();
+      //openList = new NaivePriorityQueue<float, long>();
+      openListLookup = new HashSet<long>();
+
+      long currentNode = sourceNodeId;
+
+      openList.Insert(0, currentNode);
+      openListLookup.Add(currentNode);
+      distances.Add(currentNode, 0);
+
+      while (openList.Size > 0) {
+        // get the node form the open list having the lowest score
+
+        //long dataId = openList.PeekMinValue();
+        //float dataF = openList.PeekMinKey();
+
+        KeyValuePair<float, long> data = openList.PeekMin();
+        long dataId = data.Value;
+        float dataF = data.Key;
+        currentNode = dataId;
+
+        if (currentNode == targetNodeId) {
+          return ReconstructPath(currentNode).ToArray();
+        }
+
+        // remove current from open list
+        openList.RemoveMin();
+        openListLookup.Remove(currentNode);
+
+        // add current to closed list
+        closedList.Add(currentNode);
+        closedListLookup.Add(currentNode);
+
+        //--------------
+        //Logger.LogToFile("cn = " + currentNode + " (" + dataF + ")");
+        //--------------
+
+        Dictionary<long, float> currentNeighbors = graph.GetNeighborsWithWeight(currentNode);
+        foreach (KeyValuePair<long, float> neighbor in currentNeighbors) {
+          if (closedListLookup.Contains(neighbor.Key))
+            continue;
+
+          Vertex vn = graph.GetVertex(neighbor.Key);
+          Vertex vt = graph.GetVertex(targetNodeId);
+          float costsFromStart = GetDistance(currentNode) + neighbor.Value;
+          float f = costsFromStart + costCalculator.EstimatedCosts(vn, vt);
+
+          //--------------
+          //Logger.LogToFile("    neigb:" + neighbor.Key + " (" + costsFromStart + " / " + f + ")");
+          //--------------
+
+          bool isInOpenList = openListLookup.Contains(neighbor.Key);
+          if (!isInOpenList || costsFromStart < GetDistance(neighbor.Key)) {
+            if (!isInOpenList) {
+              openList.Insert(f, neighbor.Key);
+              openListLookup.Add(neighbor.Key);
+            } else {
+              openList.DecreaseKey(f, neighbor.Key);
+            }
+            distances[neighbor.Key] = costsFromStart;
+            predecessors[neighbor.Key] = currentNode;
+          }
+        }
+        //--------------
+        //Logger.LogToFile("");
+        //--------------
+      }
+      throw new Exception(string.Format("No route found from {0} to {1}", sourceNodeId, targetNodeId));
+    }
+
+    #endregion
+
+    private float GetDistance(long id) {
+      float d;
+      if (distances.TryGetValue(id, out d)) {
+        return d;
+      } else { return float.MaxValue; }
+    }
+
+    private List<long> ReconstructPath(long nodeId) {
+      List<long> route = new List<long>();
+      long current = nodeId;
+      long next;
+
+      if (!predecessors.TryGetValue(current, out next)) {
+        return null;
+      }
+      route.Add(current);
+      while (predecessors.TryGetValue(current, out next)) {
+        current = predecessors[current];
+        route.Add(current);
+      }
+      route.Reverse();
+      return route;
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/HeuristicLab.Algorithms.GraphRouting.csproj
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/HeuristicLab.Algorithms.GraphRouting.csproj	(revision 8520)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/HeuristicLab.Algorithms.GraphRouting.csproj	(revision 8527)
@@ -59,7 +59,15 @@
     <Compile Include="AStarAlgorithmV3.cs" />
     <Compile Include="BidirectionalDijkstraAlgorithmV2.cs" />
+    <Compile Include="AStarAlgorithmV4.cs" />
+    <Compile Include="AStarAlgorithmV5.cs" />
     <Compile Include="DijkstraAlgorithmV2.cs" />
     <Compile Include="GraphRoutingAlgorithm.cs" />
+    <Compile Include="Interfaces\IHeap.cs" />
     <Compile Include="Interfaces\IRouter.cs" />
+    <Compile Include="PriorityQueues\BinaryHeap.cs" />
+    <Compile Include="PriorityQueues\BinHeap.cs" />
+    <Compile Include="PriorityQueues\BinomialHeap.cs" />
+    <Compile Include="PriorityQueues\NaivePriorityQueue.cs" />
+    <Compile Include="Utilities\Logger.cs" />
     <Compile Include="Utilities\Pair.cs" />
     <Compile Include="Plugin.cs" />
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Interfaces/IHeap.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Interfaces/IHeap.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Interfaces/IHeap.cs	(revision 8527)
@@ -0,0 +1,13 @@
+﻿
+using System.Collections.Generic;
+namespace HeuristicLab.Algorithms.GraphRouting.Interfaces {
+  public interface IHeap<K, V> {
+    int Size { get; }
+    KeyValuePair<K, V> PeekMin();
+    K PeekMinKey();
+    V PeekMinValue();
+    void Insert(K key, V value);
+    void DecreaseKey(K key, V value);
+    void RemoveMin();
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinHeap.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinHeap.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinHeap.cs	(revision 8527)
@@ -0,0 +1,112 @@
+﻿
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.GraphRouting.Interfaces;
+namespace HeuristicLab.Algorithms.GraphRouting.PriorityQueues {
+  public sealed class BinHeap<K, V> : IHeap<K, V>
+    where K : IComparable
+    where V : IComparable {
+    private class HeapElement {
+      public K Key { get; set; }
+      public V Value { get; set; }
+    }
+
+    private int capacity;
+    private int size;
+    private HeapElement[] data;
+
+    public BinHeap(int cap) {
+      size = 0;
+      capacity = cap;
+      data = new HeapElement[capacity];
+    }
+
+    public int Size {
+      get { return size; }
+    }
+
+    public void Insert(K key, V value) {
+      HeapElement elem = new HeapElement();
+      elem.Key = key;
+      elem.Value = value;
+      data[size] = elem;
+      HeapifyDown(size);
+      size++;
+    }
+
+    public KeyValuePair<K, V> PeekMin() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      return new KeyValuePair<K, V>(data[0].Key, data[0].Value);
+    }
+
+    public K PeekMinKey() {
+      return data[0].Key;
+    }
+
+    public V PeekMinValue() {
+      return data[0].Value;
+    }
+
+    public void RemoveMin() {
+      RemoveAt(0);
+    }
+
+    public void DecreaseKey(K key, V value) {
+      for (int i = 0; i < size; i++) {
+        if (data[i].Value.CompareTo(value) == 0) {
+          RemoveAt(i);
+          Insert(key, value);
+          break;
+        }
+      }
+    }
+
+    private void RemoveAt(int idx) {
+      if (size == 1) {
+        size--;
+      } else {
+        if (idx < size - 1) {
+          Swap(idx, size - 1);
+          HeapifyUp(idx);
+        }
+        size--;
+      }
+    }
+
+    private void HeapifyDown(int start) {
+      int i = start;
+      int j = (i - 1) / 2;
+      while (i > 0 && (data[i].Key.CompareTo(data[j].Key) == -1)) {
+        Swap(i, j);
+        i = j;
+        j = (i - 1) / 2;
+      }
+    }
+
+    private void HeapifyUp(int start) {
+      int idx = start;
+      int left = 2 * idx + 1;
+      int right = 2 * idx + 2;
+      while ((left < size - 1 && data[idx].Key.CompareTo(data[left].Key) != -1) ||
+             (right < size - 1 && data[idx].Key.CompareTo(data[right].Key) != -1)) {
+        if ((right >= size - 1) || (data[idx].Key.CompareTo(data[right].Key) == -1)) {
+          Swap(left, idx);
+          idx = left;
+        } else {
+          Swap(right, idx);
+          idx = right;
+        }
+        left = 2 * idx + 1;
+        right = 2 * idx + 2;
+      }
+    }
+
+    private void Swap(int i, int j) {
+      var elem = data[i];
+      data[i] = data[j];
+      data[j] = elem;
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinaryHeap.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinaryHeap.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinaryHeap.cs	(revision 8527)
@@ -0,0 +1,110 @@
+﻿
+using System;
+namespace HeuristicLab.Algorithms.GraphRouting.PriorityQueues {
+  // implementation based on C++ version from Peter Sanders
+  // http://www.mpi-inf.mpg.de/~sanders/programs/spq/
+  public sealed class BinaryHeap<K, V> where K : IComparable {
+    private class KNElement {
+      public K Key { get; set; }
+      public V Value { get; set; }
+    }
+
+    private int capacity;
+    private K supremum;
+    private int size; // index of last used element
+    private KNElement[] data;
+
+    public BinaryHeap(K sup, K infimum, int cap) {
+      size = 0;
+      capacity = cap;
+      data = new KNElement[cap + 2];
+      for (int i = 0; i < cap + 2; i++) {
+        data[i] = new KNElement();
+      }
+      data[0].Key = infimum; // sentinel
+      data[capacity + 1].Key = sup;
+      supremum = sup;
+      Reset();
+
+    }
+
+    public int Size {
+      get { return size; }
+    }
+
+    public K PeekMinKey() {
+      return data[1].Key;
+    }
+
+    public V PeekMinValue() {
+      return data[1].Value;
+    }
+
+    public void RemoveMin() {
+      int i;
+      int l;
+      int r;
+      int smallest;
+
+      if (size <= 0) {
+        throw new InvalidOperationException("Cannot delete on an empty queue");
+      }
+
+      data[1] = data[size];
+      data[size].Key = supremum;
+      size--;
+      i = 1;
+      for (; ; ) {
+        l = (i << 1);
+        r = (i << 1) + 1;
+        if ((l <= size) && (data[l].Key.CompareTo(data[i].Key) == -1)) {
+          smallest = l;
+        } else {
+          smallest = i;
+        }
+        if ((r <= size) && (data[r].Key.CompareTo(data[smallest].Key) == -1)) {
+          smallest = r;
+        }
+        if (smallest == i) break;
+        KNElement temp = data[i];
+        data[i] = data[smallest];
+        data[smallest] = temp;
+        i = smallest;
+      }
+    }
+
+    public void Insert(K key, V value) {
+      size++;
+      int hole = size;
+      while ((hole > 1) && (data[hole >> 1].Key.CompareTo(key) == 1)) {
+        data[hole] = data[hole >> 1];
+        hole = hole >> 1;
+      }
+      data[hole].Key = key;
+      data[hole].Value = value;
+    }
+
+    public void DecreaseKey(K key, V value) {
+      int pos = size;
+      while ((pos > 1) && (data[pos >> 1].Key.CompareTo(key) != 0)) {
+        pos = pos >> 1;
+      }
+      if (data[pos].Key.CompareTo(key) != 0) {
+        throw new InvalidOperationException("Key not found");
+      }
+      throw new NotImplementedException();
+    }
+
+
+
+    // reset size to 0 and fill data array with sentinels
+    private void Reset() {
+      size = 0;
+      K sup = supremum;
+      int cap = capacity;
+      for (int i = 1; i <= cap; i++) {
+        data[i].Key = sup;
+      }
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinomialHeap.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinomialHeap.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/BinomialHeap.cs	(revision 8527)
@@ -0,0 +1,237 @@
+﻿
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.GraphRouting.Interfaces;
+namespace HeuristicLab.Algorithms.GraphRouting.PriorityQueues {
+  public sealed class BinomialHeap<K, V> : IHeap<K, V>
+    where K : IComparable
+    where V : IComparable {
+    private HeapElement<K, V> head;
+    private int size;
+    private Dictionary<V, HeapElement<K, V>> elems;
+
+    public BinomialHeap() {
+      this.elems = new Dictionary<V, HeapElement<K, V>>();
+    }
+
+    public BinomialHeap(HeapElement<K, V> elem, int size) {
+      this.head = elem;
+      this.size = size;
+      this.elems = new Dictionary<V, HeapElement<K, V>>();
+    }
+
+    public int Size {
+      get { return size; }
+    }
+
+    public void Insert(K key, V value) {
+      HeapElement<K, V> elem = new HeapElement<K, V>(key, value);
+      elems.Add(elem.Value, elem);
+      BinomialHeap<K, V> heap = new BinomialHeap<K, V>(elem, 1);
+      heap = Union(heap, this);
+      head = heap.head;
+      size++;
+    }
+
+    public KeyValuePair<K, V> PeekMin() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      HeapElement<K, V> elem = PeekMinElem();
+      return new KeyValuePair<K, V>(elem.Key, elem.Value);
+    }
+
+    public K PeekMinKey() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      return PeekMinElem().Key;
+    }
+
+    public V PeekMinValue() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      return PeekMinElem().Value;
+    }
+
+    public void DecreaseKey(K key, V value) {
+      HeapElement<K, V> elem = elems[value];
+      elem.Key = key;
+      HeapElement<K, V> y = elem;
+      HeapElement<K, V> z = y.Parent;
+
+      V tempVal;
+      K tempKey;
+      while ((z != null) && (y.Key.CompareTo(z.Key) < 0)) {
+        tempVal = y.Value;
+        tempKey = y.Key;
+
+        y.Value = z.Value;
+        y.Key = z.Key;
+
+        z.Value = tempVal;
+        z.Key = tempKey;
+
+        y = z;
+        z = y.Parent;
+      }
+    }
+
+    public void RemoveMin() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+
+      HeapElement<K, V> x = head;
+      HeapElement<K, V> y = x.Sibling;
+      HeapElement<K, V> pred = x;
+      HeapElement<K, V> xPrev = null;
+
+      while (y != null) {
+        if (y.Key.CompareTo(x.Key) < 0) {
+          x = y;
+          xPrev = pred;
+        }
+        pred = y;
+        y = y.Sibling;
+      }
+
+      if (x == head) {
+        head = x.Sibling;
+      } else {
+        xPrev.Sibling = x.Sibling;
+      }
+
+      BinomialHeap<K, V> h = new BinomialHeap<K, V>();
+
+      HeapElement<K, V> z = x.Child;
+      while (z != null) {
+        HeapElement<K, V> next = z.Sibling;
+        z.Sibling = h.head;
+        h.head = z;
+        z = next;
+      }
+
+      BinomialHeap<K, V> newH = Union(this, h);
+      head = newH.head;
+
+      elems.Remove(x.Value);
+      size--;
+    }
+
+    private HeapElement<K, V> Merge(BinomialHeap<K, V> heap1, BinomialHeap<K, V> heap2) {
+      if (heap1.head == null) {
+        return heap2.head;
+      } else if (heap2.head == null) {
+        return heap1.head;
+      }
+
+      HeapElement<K, V> head;
+      HeapElement<K, V> tail;
+      HeapElement<K, V> h1Next = heap1.head;
+      HeapElement<K, V> h2Next = heap2.head;
+
+      if (heap1.head.Degree <= heap2.head.Degree) {
+        head = heap1.head;
+        h1Next = h1Next.Sibling;
+      } else {
+        head = heap2.head;
+        h2Next = h2Next.Sibling;
+      }
+
+      tail = head;
+
+      while (h1Next != null && h2Next != null) {
+        if (h1Next.Degree <= h2Next.Degree) {
+          tail.Sibling = h1Next;
+          h1Next = h1Next.Sibling;
+        } else {
+          tail.Sibling = h2Next;
+          h2Next = h2Next.Sibling;
+        }
+        tail = tail.Sibling;
+      }
+
+      if (h1Next != null) {
+        tail.Sibling = h1Next;
+      } else {
+        tail.Sibling = h2Next;
+      }
+
+      return head;
+    }
+
+    private BinomialHeap<K, V> Union(BinomialHeap<K, V> h1, BinomialHeap<K, V> h2) {
+      HeapElement<K, V> elem = Merge(h1, h2);
+      BinomialHeap<K, V> h = new BinomialHeap<K, V>(elem, 0);
+      if (h.head == null) {
+        return h;
+      }
+      h.size = h1.size + h2.size;
+
+      HeapElement<K, V> xPrev = null;
+      HeapElement<K, V> x = h.head;
+      HeapElement<K, V> xNext = x.Sibling;
+
+      while (xNext != null) {
+        if ((x.Degree != xNext.Degree) || (xNext.Sibling != null && xNext.Sibling.Degree == x.Degree)) {
+          xPrev = x;
+          x = xNext;
+        } else {
+          if (x.Key.CompareTo(xNext.Key) <= 0) {
+            x.Sibling = xNext.Sibling;
+            Link(xNext, x);
+          } else {
+            if (xPrev == null) {
+              h.head = xNext;
+            } else {
+              xPrev.Sibling = xNext;
+            }
+            Link(x, xNext);
+            x = xNext;
+          }
+        }
+        xNext = x.Sibling;
+      }
+      return h;
+    }
+
+    private void Link(HeapElement<K, V> y, HeapElement<K, V> z) {
+      y.Parent = z;
+      y.Sibling = z.Child;
+      z.Child = y;
+      z.Degree = z.Degree + 1;
+    }
+
+    private HeapElement<K, V> PeekMinElem() {
+      HeapElement<K, V> min = head;
+      HeapElement<K, V> next = min.Sibling;
+      while (next != null) {
+        if (min.Key.CompareTo(next.Key) > 0) {
+          min = next;
+        }
+        next = next.Sibling;
+      }
+      return min;
+    }
+
+  }
+  public class HeapElement<K, V> {
+    public K Key;
+    public V Value;
+    public int Degree;
+    public HeapElement<K, V> Parent;
+    public HeapElement<K, V> Child;
+    public HeapElement<K, V> Sibling;
+
+    public HeapElement(K key, V value) {
+      this.Key = key;
+      this.Value = value;
+      this.Parent = null;
+      this.Child = null;
+      this.Sibling = null;
+      this.Degree = 0;
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/NaivePriorityQueue.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/NaivePriorityQueue.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/PriorityQueues/NaivePriorityQueue.cs	(revision 8527)
@@ -0,0 +1,112 @@
+﻿using System;
+using System.Collections.Generic;
+using HeuristicLab.Algorithms.GraphRouting.Interfaces;
+
+namespace HeuristicLab.Algorithms.GraphRouting.PriorityQueues {
+  public class NaivePriorityQueue<K, V> : IHeap<K, V>
+    where K : IComparable
+    where V : IComparable {
+    private Node head;
+
+    private int size;
+    public int Size {
+      get { return size; }
+    }
+
+    public NaivePriorityQueue() {
+
+    }
+
+    public void Insert(K key, V value) {
+      Node n = new Node(key, value);
+      if (head == null) {
+        head = n;
+      } else if (head.Key.CompareTo(n.Key) >= 0) {
+        n.Next = head;
+        head = n;
+      } else {
+        Node curr = head;
+        while (curr.Next != null && (curr.Next.Key.CompareTo(n.Key) <= 0)) {
+          curr = curr.Next;
+        }
+        n.Next = curr.Next;
+        curr.Next = n;
+      }
+      size++;
+    }
+
+    public KeyValuePair<K, V> PeekMin() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      KeyValuePair<K, V> pair = new KeyValuePair<K, V>(head.Key, head.Value);
+      return pair;
+    }
+
+    public K PeekMinKey() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      return head.Key;
+    }
+
+    public V PeekMinValue() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      return head.Value;
+    }
+
+    public void DecreaseKey(K key, V value) {
+      Node n = null;
+      Node curr = head;
+      Node prev = null;
+
+      // search for node to be updated
+      while (curr != null) {
+        if (curr.Value.CompareTo(value) == 0) {
+          n = curr;
+          break;
+        }
+        prev = curr;
+        curr = curr.Next;
+      }
+
+      // check if node was found
+      if (n == null) {
+        throw new InvalidOperationException("Value not found");
+      }
+
+      //update key
+      n.Key = key;
+
+      // if node is head of list we're done ...
+
+      if (prev != null) {
+        // ... otherwise remove from list and reinsert it
+        prev.Next = n.Next;
+        Insert(n.Key, n.Value);
+        n = null;
+      }
+    }
+
+    public void RemoveMin() {
+      if (size == 0) {
+        throw new InvalidOperationException("Heap is empty");
+      }
+      head = head.Next;
+      size--;
+    }
+
+    private class Node {
+      public K Key;
+      public V Value;
+      public Node Next;
+
+      public Node(K key, V value) {
+        this.Key = key;
+        this.Value = value;
+      }
+    }
+  }
+}
Index: branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Utilities/Logger.cs
===================================================================
--- branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Utilities/Logger.cs	(revision 8527)
+++ branches/RoutePlanning/HeuristicLab.Algorithms.GraphRouting/3.3/Utilities/Logger.cs	(revision 8527)
@@ -0,0 +1,47 @@
+﻿using System;
+using System.IO;
+
+namespace HeuristicLab.Algorithms.GraphRouting.Utilities {
+  public static class Logger {
+    //public static void writeToLogFile(string logMessage) {
+    //  string strLogMessage = string.Empty;
+    //  string strLogFile = "LogFile.txt";
+    //  StreamWriter swLog;
+
+    //  //strLogMessage = string.Format("{0}: {1}", DateTime.Now, logMessage);
+    //  strLogMessage = logMessage;
+
+    //  if (!File.Exists(strLogFile)) {
+    //    swLog = new StreamWriter(strLogFile);
+    //  } else {
+    //    swLog = File.AppendText(strLogFile);
+    //  }
+
+    //  swLog.WriteLine(strLogMessage);
+    //  swLog.WriteLine();
+
+    //  swLog.Close();
+
+    //}
+
+    static StreamWriter LogWriter;
+
+    public static void LogToFile(string message) {
+      try {
+        if (!File.Exists("LogFile.txt")) {
+          LogWriter = new StreamWriter("LogFile.txt");
+        } else {
+          LogWriter = File.AppendText("LogFile.txt");
+        }
+        LogWriter.WriteLine(message);
+        LogWriter.Flush();
+      }
+      catch (Exception) { }
+      finally {
+        if (LogWriter != null) {
+          LogWriter.Close();
+        }
+      }
+    }
+  }
+}
