def __init__(self, port=6881, authkey="rectangle", constraints=None, output=None, verbose=0):


        self.solutions = []
        self.biob_cons = ["z2_cons", "z1_cons"] if constraints is None else constraints
        self._hypervol = HyperVolume()
        self._manager = self.__make_manager_server(port, authkey)
        #concurrent stuff
        self.task_q = self._manager.get_task_q()
        self.done_q = self._manager.get_done_q()
        self.empty_rectangles = []
        self.output = output
        self.verbose = verbose
Exemple #2
0
    def approximate(self, gap, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = ParetoFilter.filter(sorted(sols),
                                   rel_tol=rel_tol,
                                   abs_tol=abs_tol)

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

            print "\n", "Starting rectangle refinement\n"

        curr_gap = HyperVolume.calc_hypervol_gap(sols,
                                                 [sols[0].objs, sols[-1].objs],
                                                 [])
        if curr_gap < gap:
            return sols

        self.approximate_rectangle(gap,
                                   init_recs=sols,
                                   rel_tol=1e-05,
                                   abs_tol=0.0001)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE", None, None, None, None))

        self._manager.shutdown()
        return self.solutions
    def __init__(self, port=6881, authkey="rectangle", constraints=None, output=None, verbose=0):


        self.solutions = []
        self.biob_cons = ["z2_cons", "z1_cons"] if constraints is None else constraints
        self._hypervol = HyperVolume()
        self._manager = self.__make_manager_server(port, authkey)
        #concurrent stuff
        self.task_q = self._manager.get_task_q()
        self.done_q = self._manager.get_done_q()
        self.empty_rectangles = []
        self.output = output
        self.verbose = verbose
    def approximate(self, gap, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = ParetoFilter.filter(sorted(sols),rel_tol=rel_tol, abs_tol=abs_tol)

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

            print "\n","Starting rectangle refinement\n"

        curr_gap = HyperVolume.calc_hypervol_gap(sols, [sols[0].objs, sols[-1].objs], [])
        if curr_gap < gap:
            return sols

        self.approximate_rectangle(gap, init_recs=sols, rel_tol=1e-05, abs_tol=0.0001)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE",None,None,None,None))

        self._manager.shutdown()
        return self.solutions
class RectangleEpsilonGridManager(object):
    """
        This is prarallel implementation of
        the epsilon contraint method with precomputed boundaries

        CPLEX floating point accuracy is b default ~1e-6
    """

    def __init__(self, port=6881, authkey="rectangle", constraints=None, output=None, verbose=0):


        self.solutions = []
        self.biob_cons = ["z2_cons", "z1_cons"] if constraints is None else constraints
        self._hypervol = HyperVolume()
        self._manager = self.__make_manager_server(port, authkey)
        #concurrent stuff
        self.task_q = self._manager.get_task_q()
        self.done_q = self._manager.get_done_q()
        self.empty_rectangles = []
        self.output = output
        self.verbose = verbose

    @staticmethod
    def __isclose(a, b, rel_tol=1e-09, abs_tol=0.00001):
        return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

    def __make_manager_server(self, port, authkey):
        """
         Starts a manager server
        :return: Manager object
        """

        job_q = mp.JoinableQueue()
        result_q = mp.Queue()
        result_eps_q = mp.Queue()
        task_q = mp.JoinableQueue()

        # This is based on the examples in the official docs of multiprocessing.
        # get_{job|result}_q return synchronized proxies for the actual Queue
        # objects.
        class JobQueueManager(mp.managers.SyncManager):
            pass

        JobQueueManager.register('get_task_q', callable=lambda: job_q)
        JobQueueManager.register('get_done_q', callable=lambda: result_q)
        JobQueueManager.register('get_eps_done_q', callable=lambda: result_eps_q)
        JobQueueManager.register('get_task_q', callable=lambda: task_q)
        manager = JobQueueManager(address=('', port), authkey=authkey)

        manager.start()
        print 'Server started at %s:%s. Authentication: %s' % (socket.gethostbyname(socket.gethostname()),port,authkey)
        return manager

    def solve_grid(self, nof_sol=1):


        solutions = []
        #init problems to solve
        self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
        self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

        self.task_q.join()

        b = [None, None]
        warm = [None, None]
        while not self.done_q.empty():
            pos, sol, warmstart, origin_rect = self.done_q.get()
            print "Edge Point ", sol.objs
            solutions.append(sol)
            b[pos] = sol.objs
            warm[pos] = warmstart[pos]

        #temporal save
        #pcl.dump(solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

        delta = 1/(nof_sol)
        diff = b[1][1] - b[0][1]
        alphas = [delta*i*diff for i in xrange(1, nof_sol+1)]

        c = 0
        for i in xrange(nof_sol):
            print "Bounds: ", b[0][1]+alphas[i]
            self.task_q.put((0, 1, b[0][1]+alphas[i], warm, tuple(b)))
            c += 1

        while c:
            _, sol, _, _ = self.done_q.get()
            print sol
            c -= 1
            solutions.append(sol)
            #pcl.dump(solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

        print "solved all epsilon grids"
        return solutions


    def solve_rectangle(self, init_recs=None, rel_tol=1e-05, abs_tol=0.0001):
        """
            solve rectangle spliting after intial deterimnation fo rectangles
        """
        eps=abs_tol
        isclose =RectangleEpsilonGridManager.__isclose
        task_count = 0
        if init_recs:
            b = [init_recs[0].objs, init_recs[-1].objs]
            self.solutions.extend(init_recs)
            for i in xrange(len(init_recs)-1):
                task_count += 1
                zi = init_recs[i]
                zj = init_recs[i+1]
                warm = [zi.warm_start, zj.warm_start]
                rec = [zi.objs, zj.objs]
                rec_b = (rec[0][1]+rec[1][1])/2
                self.task_q.put((0, 1, rec_b, warm, tuple(rec)))
        else:
            task_count = 2
            #init problems to solve
            self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
            self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

            self.task_q.join()


            b = [None, None]
            warm = [None, None]
            while task_count:
                pos, sol, warmstart, origin_rect = self.done_q.get()
                if pos is None:
                    continue
                task_count -= 1
                self.solutions.append(sol)
                #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

                b[pos] = sol.objs
                warm[pos] = warmstart[pos]

            rec_b = (b[0][1]+b[1][1])/2
            task_count = 1
            self.task_q.put((0, 1, rec_b, warm, b))

        while task_count:

            pos, sol, warm, origin_rect = self.done_q.get()

            #lexmin2
            if pos:
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])): 
                   if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])):
                    #if not numpy.allclose(sol.objs, origin_rect[0], rtol=1e-04, atol=1e-02):
                        rec = (origin_rect[0], sol.objs)
                        self.solutions.append(sol)
                        
                        if abs(rec[0][0]-rec[1][0]) > eps:
                            rec_b = (rec[0][1]+rec[1][1])/2
                            self.task_q.put((0, 1, rec_b, warm, rec))
                            task_count += 1
            #lexmin1
            else:
                rec_t = sol.objs[0]-eps
                self.task_q.put((1, 0, rec_t, warm, origin_rect))
                task_count += 1
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])):
                   if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    #if not numpy.allclose(sol.objs, origin_rect[1], rtol=1e-04, atol=1e-02):
                        rec = (sol.objs, origin_rect[1])
                        self.solutions.append(sol)

                        if abs(rec[0][0]-rec[1][0]) > eps:
                            rec_b = (rec[0][1]+rec[1][1])/2
                            self.task_q.put((0, 1, rec_b, warm, rec))
                            task_count += 1

            task_count -= 1

            if self.verbose:
                print "Current Rectangle ", origin_rect
                print "Solution ", sol
                print "Lexmin:",pos
                print "Solutions ", len(self.solutions)
                print "Rectangle Size: ", abs(origin_rect[0][0]-origin_rect[1][0])
                print "Tasks still running: ", task_count

        return self.solutions


    def approximate_rectangle(self, gap, init_recs=None, rel_tol=1e-05, abs_tol=0.0001):
        eps = abs_tol
        verbose = self.verbose
        isclose = RectangleEpsilonGridManager.__isclose
        task_count = 0
        proof_not_empty_rec = {}
        empty_rect = set()

        if init_recs:
            init_rect = [init_recs[0].objs, init_recs[-1].objs]
            self.solutions.extend(init_recs)
            for i in xrange(len(init_recs)-1):
                task_count += 1
                zi = init_recs[i]
                zj = init_recs[i+1]
                warm = [zi.warm_start, zj.warm_start]
                rec = [zi.objs, zj.objs]
                rec_b = (rec[0][1]+rec[1][1])/2
                self.task_q.put((0, 1, rec_b, warm, tuple(rec)))
        else:
            task_count += 2
            self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
            self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

            self.task_q.join()

            init_rect = [None, None]
            warm = [None, None]
            while task_count:
                pos, sol, warmstart, origin_rect = self.done_q.get()

                if pos is None:
                    continue
                task_count -= 1
                heapq.heappush(self.solutions, sol)
                #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

                init_rect[pos] = sol.objs
                warm[pos] = warmstart[pos]
            init_rect = tuple(init_rect)
            rec_b = (init_rect[0][1]+init_rect[1][1])/2
            task_count += 1
            self.task_q.put((0, 1, rec_b, warm, init_rect))

        while task_count > 0:
            pos, sol, warm, origin_rect = self.done_q.get()

            if verbose:
                print
                print "Current Rectangle ", origin_rect
                print "Solution: ", sol
                print "Tasks still running: ", task_count

            if pos:
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])) and not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    rec = (origin_rect[0], sol.objs)
                    heapq.heappush(self.solutions, sol)
                    #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))
                    if abs(rec[0][0]-rec[1][0]) > eps:
                        rec_b = (rec[0][1]+rec[1][1])/2
                        self.task_q.put((0, 1, rec_b, warm, rec))
                        task_count += 1

                    if origin_rect in proof_not_empty_rec:
                        print "Rectanlge ",(sol.objs, proof_not_empty_rec[origin_rect])," is empty"
                        empty_rect.add((sol.objs, proof_not_empty_rec[origin_rect]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break

                    else:
                        #empty_rect.add((sol.objs, origin_rect[1]))
                        proof_not_empty_rec[origin_rect] = sol.objs

                else:

                    if origin_rect in proof_not_empty_rec:
                        print "Rectanlge ",(origin_rect[0], proof_not_empty_rec[origin_rect])," is empty"
                        empty_rect.add((origin_rect[0], proof_not_empty_rec[origin_rect]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break
                    else:
                        proof_not_empty_rec[origin_rect] = origin_rect[0]

            #lexmin1
            else:
                rec_t = sol.objs[0]-eps
                self.task_q.put((1, 0, rec_t, warm, origin_rect))
                task_count += 1

                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])) and not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    rec = (sol.objs, origin_rect[1])
                    heapq.heappush(self.solutions, sol)

                    if abs(rec[0][0]-rec[1][0]) > eps:
                        rec_b = (rec[0][1]+rec[1][1])/2
                        self.task_q.put((0, 1, rec_b, warm, rec))
                        task_count += 1

                    if origin_rect in proof_not_empty_rec:
                        empty_rect.add((proof_not_empty_rec[origin_rect], sol.objs))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        if verbose:
                            print "Rectanlge ",(proof_not_empty_rec[origin_rect], origin_rect[1])," is empty"
                            print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break
                    else:
                        proof_not_empty_rec[origin_rect] = sol.objs
                else:
                    if origin_rect in proof_not_empty_rec:
                        empty_rect.add((proof_not_empty_rec[origin_rect], origin_rect[1]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        if verbose:
                            print "Rectanlge ",(proof_not_empty_rec[origin_rect], sol.objs)," is empty"
                            print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break

                    else:
                        proof_not_empty_rec[origin_rect] = origin_rect[1]

            task_count -= 1


        if verbose:
            print "Last hypervol gap: ", self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)

        return self.solutions


    def solve(self, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = sorted(ParetoFilter.filter(sols,rel_tol=rel_tol, abs_tol=abs_tol))

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

        #pcl.dump(sols, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))
        self.solve_rectangle(init_recs=sols,rel_tol=rel_tol, abs_tol=abs_tol)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE",None,None,None,None))
        self._manager.shutdown()
        return self.solutions

    def approximate(self, gap, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = ParetoFilter.filter(sorted(sols),rel_tol=rel_tol, abs_tol=abs_tol)

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

            print "\n","Starting rectangle refinement\n"

        curr_gap = HyperVolume.calc_hypervol_gap(sols, [sols[0].objs, sols[-1].objs], [])
        if curr_gap < gap:
            return sols

        self.approximate_rectangle(gap, init_recs=sols, rel_tol=1e-05, abs_tol=0.0001)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE",None,None,None,None))

        self._manager.shutdown()
        return self.solutions
class RectangleEpsilonGridManager(object):
    """
        This is prarallel implementation of
        the epsilon contraint method with precomputed boundaries

        CPLEX floating point accuracy is b default ~1e-6
    """

    def __init__(self, port=6881, authkey="rectangle", constraints=None, output=None, verbose=0):


        self.solutions = []
        self.biob_cons = ["z2_cons", "z1_cons"] if constraints is None else constraints
        self._hypervol = HyperVolume()
        self._manager = self.__make_manager_server(port, authkey)
        #concurrent stuff
        self.task_q = self._manager.get_task_q()
        self.done_q = self._manager.get_done_q()
        self.empty_rectangles = []
        self.output = output
        self.verbose = verbose

    @staticmethod
    def __isclose(a, b, rel_tol=1e-09, abs_tol=0.00001):
        return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

    def __make_manager_server(self, port, authkey):
        """
         Starts a manager server
        :return: Manager object
        """

        job_q = mp.JoinableQueue()
        result_q = mp.Queue()
        result_eps_q = mp.Queue()
        task_q = mp.JoinableQueue()

        # This is based on the examples in the official docs of multiprocessing.
        # get_{job|result}_q return synchronized proxies for the actual Queue
        # objects.
        class JobQueueManager(mp.managers.SyncManager):
            pass

        JobQueueManager.register('get_task_q', callable=lambda: job_q)
        JobQueueManager.register('get_done_q', callable=lambda: result_q)
        JobQueueManager.register('get_eps_done_q', callable=lambda: result_eps_q)
        JobQueueManager.register('get_task_q', callable=lambda: task_q)
        manager = JobQueueManager(address=('', port), authkey=authkey)

        manager.start()
        print 'Server started at %s:%s. Authentication: %s' % (socket.gethostbyname(socket.gethostname()),port,authkey)
        return manager

    def solve_grid(self, nof_sol=1):


        solutions = []
        #init problems to solve
        self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
        self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

        self.task_q.join()

        b = [None, None]
        warm = [None, None]
        while not self.done_q.empty():
            pos, sol, warmstart, origin_rect = self.done_q.get()
            print "Edge Point ", sol.objs
            solutions.append(sol)
            b[pos] = sol.objs
            warm[pos] = warmstart[pos]

        #temporal save
        #pcl.dump(solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

        delta = 1/(nof_sol)
        diff = b[1][1] - b[0][1]
        alphas = [delta*i*diff for i in xrange(1, nof_sol+1)]

        c = 0
        for i in xrange(nof_sol):
            print "Bounds: ", b[0][1]+alphas[i]
            self.task_q.put((0, 1, b[0][1]+alphas[i], warm, tuple(b)))
            c += 1

        while c:
            _, sol, _, _ = self.done_q.get()
            print sol
            c -= 1
            solutions.append(sol)
            #pcl.dump(solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

        print "solved all epsilon grids"
        return solutions


    def solve_rectangle(self, init_recs=None, rel_tol=1e-05, abs_tol=0.0001):
        """
            solve rectangle spliting after intial deterimnation fo rectangles
        """
        eps=abs_tol
        isclose =RectangleEpsilonGridManager.__isclose
        task_count = 0
        if init_recs:
            b = [init_recs[0].objs, init_recs[-1].objs]
            self.solutions.extend(init_recs)
            for i in xrange(len(init_recs)-1):
                task_count += 1
                zi = init_recs[i]
                zj = init_recs[i+1]
                warm = [zi.warm_start, zj.warm_start]
                rec = [zi.objs, zj.objs]
                rec_b = (rec[0][1]+rec[1][1])/2
                self.task_q.put((0, 1, rec_b, warm, tuple(rec)))
        else:
            task_count = 2
            #init problems to solve
            self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
            self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

            self.task_q.join()


            b = [None, None]
            warm = [None, None]
            while task_count:
                pos, sol, warmstart, origin_rect = self.done_q.get()
                if pos is None:
                    continue
                task_count -= 1
                self.solutions.append(sol)
                #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

                b[pos] = sol.objs
                warm[pos] = warmstart[pos]

            rec_b = (b[0][1]+b[1][1])/2
            task_count = 1
            self.task_q.put((0, 1, rec_b, warm, b))

        while task_count:

            pos, sol, warm, origin_rect = self.done_q.get()

            #lexmin2
            if pos:
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])): 
                   if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])):
                    #if not numpy.allclose(sol.objs, origin_rect[0], rtol=1e-04, atol=1e-02):
                        rec = (origin_rect[0], sol.objs)
                        self.solutions.append(sol)
                        
                        if abs(rec[0][0]-rec[1][0]) > eps:
                            rec_b = (rec[0][1]+rec[1][1])/2
                            self.task_q.put((0, 1, rec_b, warm, rec))
                            task_count += 1
            #lexmin1
            else:
                rec_t = sol.objs[0]-eps
                self.task_q.put((1, 0, rec_t, warm, origin_rect))
                task_count += 1
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])):
                   if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    #if not numpy.allclose(sol.objs, origin_rect[1], rtol=1e-04, atol=1e-02):
                        rec = (sol.objs, origin_rect[1])
                        self.solutions.append(sol)

                        if abs(rec[0][0]-rec[1][0]) > eps:
                            rec_b = (rec[0][1]+rec[1][1])/2
                            self.task_q.put((0, 1, rec_b, warm, rec))
                            task_count += 1

            task_count -= 1

            if self.verbose:
                print "Current Rectangle ", origin_rect
                print "Solution ", sol
                print "Lexmin:",pos
                print "Solutions ", len(self.solutions)
                print "Rectangle Size: ", abs(origin_rect[0][0]-origin_rect[1][0])
                print "Tasks still running: ", task_count

        return self.solutions


    def approximate_rectangle(self, gap, init_recs=None, rel_tol=1e-05, abs_tol=0.0001):
        eps = abs_tol
        verbose = self.verbose
        isclose = RectangleEpsilonGridManager.__isclose
        task_count = 0
        proof_not_empty_rec = {}
        empty_rect = set()

        if init_recs:
            init_rect = [init_recs[0].objs, init_recs[-1].objs]
            self.solutions.extend(init_recs)
            for i in xrange(len(init_recs)-1):
                task_count += 1
                zi = init_recs[i]
                zj = init_recs[i+1]
                warm = [zi.warm_start, zj.warm_start]
                rec = [zi.objs, zj.objs]
                rec_b = (rec[0][1]+rec[1][1])/2
                self.task_q.put((0, 1, rec_b, warm, tuple(rec)))
        else:
            task_count += 2
            self.task_q.put((0, 1, cplex.infinity, [None, None], ((None, None), (None, None))))
            self.task_q.put((1, 0, cplex.infinity, [None, None], ((None, None), (None, None))))

            self.task_q.join()

            init_rect = [None, None]
            warm = [None, None]
            while task_count:
                pos, sol, warmstart, origin_rect = self.done_q.get()

                if pos is None:
                    continue
                task_count -= 1
                heapq.heappush(self.solutions, sol)
                #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))

                init_rect[pos] = sol.objs
                warm[pos] = warmstart[pos]
            init_rect = tuple(init_rect)
            rec_b = (init_rect[0][1]+init_rect[1][1])/2
            task_count += 1
            self.task_q.put((0, 1, rec_b, warm, init_rect))

        while task_count > 0:
            pos, sol, warm, origin_rect = self.done_q.get()

            if verbose:
                print
                print "Current Rectangle ", origin_rect
                print "Solution: ", sol
                print "Tasks still running: ", task_count

            if pos:
                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])) and not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    rec = (origin_rect[0], sol.objs)
                    heapq.heappush(self.solutions, sol)
                    #pcl.dump(self.solutions, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))
                    if abs(rec[0][0]-rec[1][0]) > eps:
                        rec_b = (rec[0][1]+rec[1][1])/2
                        self.task_q.put((0, 1, rec_b, warm, rec))
                        task_count += 1

                    if origin_rect in proof_not_empty_rec:
                        print "Rectanlge ",(sol.objs, proof_not_empty_rec[origin_rect])," is empty"
                        empty_rect.add((sol.objs, proof_not_empty_rec[origin_rect]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break

                    else:
                        #empty_rect.add((sol.objs, origin_rect[1]))
                        proof_not_empty_rec[origin_rect] = sol.objs

                else:

                    if origin_rect in proof_not_empty_rec:
                        print "Rectanlge ",(origin_rect[0], proof_not_empty_rec[origin_rect])," is empty"
                        empty_rect.add((origin_rect[0], proof_not_empty_rec[origin_rect]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break
                    else:
                        proof_not_empty_rec[origin_rect] = origin_rect[0]

            #lexmin1
            else:
                rec_t = sol.objs[0]-eps
                self.task_q.put((1, 0, rec_t, warm, origin_rect))
                task_count += 1

                if not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[1])) and not all(isclose(a,b, rel_tol=rel_tol, abs_tol=abs_tol) for a,b in itr.izip(sol.objs, origin_rect[0])):
                    rec = (sol.objs, origin_rect[1])
                    heapq.heappush(self.solutions, sol)

                    if abs(rec[0][0]-rec[1][0]) > eps:
                        rec_b = (rec[0][1]+rec[1][1])/2
                        self.task_q.put((0, 1, rec_b, warm, rec))
                        task_count += 1

                    if origin_rect in proof_not_empty_rec:
                        empty_rect.add((proof_not_empty_rec[origin_rect], sol.objs))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        if verbose:
                            print "Rectanlge ",(proof_not_empty_rec[origin_rect], origin_rect[1])," is empty"
                            print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break
                    else:
                        proof_not_empty_rec[origin_rect] = sol.objs
                else:
                    if origin_rect in proof_not_empty_rec:
                        empty_rect.add((proof_not_empty_rec[origin_rect], origin_rect[1]))
                        del proof_not_empty_rec[origin_rect]

                        cur_gap = self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)
                        if verbose:
                            print "Rectanlge ",(proof_not_empty_rec[origin_rect], sol.objs)," is empty"
                            print "Current Hypervol. gap is: ", cur_gap
                        if cur_gap < gap:
                           break

                    else:
                        proof_not_empty_rec[origin_rect] = origin_rect[1]

            task_count -= 1


        if verbose:
            print "Last hypervol gap: ", self._hypervol.calc_hypervol_gap(self.solutions, init_rect, empty_rect)

        return self.solutions


    def solve(self, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = sorted(ParetoFilter.filter(sols,rel_tol=rel_tol, abs_tol=abs_tol))

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

        #pcl.dump(sols, open(".".join(args.output.split(".")[:-1])+"_temp.pcl", "w"))
        self.solve_rectangle(init_recs=sols,rel_tol=rel_tol, abs_tol=abs_tol)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE",None,None,None,None))
        self._manager.shutdown()
        return self.solutions

    def approximate(self, gap, nof_sol=3, rel_tol=1e-05, abs_tol=0.0001):
        sols = self.solve_grid(nof_sol=nof_sol)

        #filter non pareto points
        sols = ParetoFilter.filter(sorted(sols),rel_tol=rel_tol, abs_tol=abs_tol)

        if self.verbose:
            print "Filtered pareto points"
            for s in sols:
                print s

            print "\n","Starting rectangle refinement\n"

        curr_gap = HyperVolume.calc_hypervol_gap(sols, [sols[0].objs, sols[-1].objs], [])
        if curr_gap < gap:
            return sols

        self.approximate_rectangle(gap, init_recs=sols, rel_tol=1e-05, abs_tol=0.0001)
        for _ in xrange(nof_sol):
            self.task_q.put(("DONE",None,None,None,None))

        self._manager.shutdown()
        return self.solutions