Generates passwords in order between upto N_max
        @N_max is the maximum size of the priority queue will be tolerated,
        so if the size of the queue is bigger than 1.5 * N_max, it will shrink
        the size to 0.75 * N_max
        @n is the number of password to generate.
        **This function is expensive, and shuold be called only if necessary.
        Cache its call as much as possible**
        # TODO: Need to recheck how to make sure this is working.

def generate_pws_in_order(self, n, filter_func=None, N_max=1e6):
        """
        Generates passwords in order between upto N_max
        @N_max is the maximum size of the priority queue will be tolerated,
        so if the size of the queue is bigger than 1.5 * N_max, it will shrink
        the size to 0.75 * N_max
        @n is the number of password to generate.
        **This function is expensive, and shuold be called only if necessary.
        Cache its call as much as possible**
        # TODO: Need to recheck how to make sure this is working.
        """
        # assert alpha < beta, 'alpha={} must be less than beta={}'.format(alpha, beta)
        states = [(-1.0, helper.START)]
        # get the topk first
        p_min = 1e-9 / (n**2)   # max 1 million entries in the heap 
        ret = []
        done = set()
        already_added_in_heap = set()
        while len(ret) < n and len(states) > 0:
        # while n > 0 and len(states) > 0:
            p, s = heapq.heappop(states)
            if p < 0:
                p = -p
            if s in done: continue
            assert s[0] == helper.START, "Broken s: {!r}".format(s)
            if s[-1] == helper.END:
                done.add(s)
                clean_s = s[1:-1]
                if filter_func is None or filter_func(clean_s):
                    ret.append((clean_s, p))
                    # n -= 1
                    # yield (clean_s, p)
            else:
                for c, f in self._get_next(s).items():
                    if (f*p < p_min or (s+c) in done or
                        (s+c) in already_added_in_heap):
                        continue
                    already_added_in_heap.add(s+c)
                    heapq.heappush(states, (-f*p, s+c))
            if len(states) > N_max * 3 / 2:
                print("Heap size: {}. ret={}. (expected: {}) s={!r}"
                      .format(len(states), len(ret), n, s))
                print("The size of states={}.  Still need={} pws. Truncating"
                      .format(len(states), n - len(ret)))
                states = heapq.nsmallest(int(N_max * 3/4), states)
                print("Done")
        return ret