Esempio n. 1
0
def generate_cids(model, prefix=(), **kwds):
    """Generate forward and reverse mappings between model
    components and deterministic, unique identifiers that
    are safe to serialize or use as dictionary keys."""
    object_to_cid = pmo.ComponentMap()
    cid_to_object = collections.OrderedDict()
    if hasattr(pmo, "preorder_traversal"):  # pragma:nocover
        fn = lambda *args, **kwds: pmo.preorder_traversal(model, *args, **kwds)
    else:  # pragma:nocover
        fn = model.preorder_traversal
    try:
        fn(return_key=True)
    except TypeError:
        traversal = fn(**kwds)
        obj_ = six.next(traversal)
        assert obj_ is model
        object_to_cid[model] = prefix
        cid_to_object[prefix] = model
        for obj in traversal:
            parent = obj.parent
            key = obj.storage_key
            cid_ = object_to_cid[obj] = object_to_cid[parent] + (key, )
            cid_to_object[cid_] = obj
    else:  # pragma:nocover
        traversal = fn(return_key=True, **kwds)
        obj_ = six.next(traversal)[1]
        assert obj_ is model
        object_to_cid[model] = prefix
        cid_to_object[prefix] = model
        for key, obj in traversal:
            parent = obj.parent
            cid_ = object_to_cid[obj] = object_to_cid[parent] + (key, )
            cid_to_object[cid_] = obj
    return object_to_cid, cid_to_object
Esempio n. 2
0
    def _branch_x(self, parent):
        N = range(len(self.W))
        orig_bounds = pmo.ComponentMap()
        orig_bounds.update((yi, yi.bounds)
                           for yi in self.model.y.components())
        orig_bounds.update((xij, xij.bounds)
                           for xij in self.model.x.components())

        # do some simple preprocessing to reduce
        # the branch space
        for i in N:
            assert self.model.y[i].lb <= self.model.y[i].ub
            assert self.model.y[i].lb in (0,1)
            assert self.model.y[i].ub in (0,1)
            if self.model.y[i].ub == 0:
                for j in N:
                    assert self.model.x[i,j].lb == 0
                    self.model.x[i,j].ub = 0
        unassigned_items = []
        for j in N:
            assigned = sum(self.model.x[i,j].lb for i in N)
            if assigned == 0:
                unassigned_items.append(j)
            else:
                assert assigned == 1
                for i in N:
                    if self.model.x[i,j].lb == 0:
                        self.model.x[i,j].ub = 0
        # find an item that is not already fixed into a bin
        bv = None
        for j in unassigned_items:
            for i in N:
                if (self.model.x[i,j].lb == 0) and \
                   (self.model.x[i,j].ub == 1):
                    bv = self.model.x[i,j]
                    break
            if bv is not None:
                break
        else:                                     #pragma:nocover
            return ()

        assert bv is not None
        children = [parent.new_child(),
                    parent.new_child()]
        bv.lb = bv.ub = 1
        self.save_state(children[0])
        bv.lb = bv.ub = 0
        self.save_state(children[1])

        # reset bounds
        for var in orig_bounds:
            var.bounds = orig_bounds[var]

        return children
Esempio n. 3
0
    def _branch_y(self, parent):

        N = range(len(self.W))
        for i in N:
            yi = self.model.y[i]
            assert yi.lb in (0,1), \
                str(yi.name)+" "+str(yi.bounds)
            assert yi.ub in (0,1), \
                str(yi.name)+" "+str(yi.bounds)
            if yi.lb == 0:
                if yi.ub == 1:
                    break
                else:
                    assert yi.ub == 0
            else:
                assert yi.lb == 1
                assert yi.lb == yi.ub
        else:
            # there is no branching left to do
            return ()

        for k in range(i,len(self.W)):
            assert self.model.y[k].lb == 0
            assert self.model.y[k].ub in (0,1)

        orig_bounds = pmo.ComponentMap()
        orig_bounds.update((yi, yi.bounds)
                           for yi in self.model.y.components())
        orig_bounds.update((xij, xij.bounds)
                           for xij in self.model.x.components())

        children = [parent.new_child(),
                    parent.new_child()]

        # first branch: fix this bin on
        self.model.y[i].lb = self.model.y[i].ub = 1
        self.save_state(children[0])

        # second branch: fix this bin off, as well as all
        #                bins following it
        for k in range(i,len(self.W)):
            self.model.y[k].lb = self.model.y[k].ub = 0
            for j in N:
                assert self.model.x[k,j].lb == 0
                self.model.x[k,j].ub = 0
        self.save_state(children[1])

        # reset bounds
        for var in orig_bounds:
            var.bounds = orig_bounds[var]

        return children
Esempio n. 4
0
    def __init__(self, V, W,
                 pyomo_solver="ipopt",
                 pyomo_solver_io="nl",
                 integer_tolerance=1e-4):
        assert V > 0
        assert integer_tolerance > 0
        self.V = V
        self.W = W
        self._integer_tolerance = integer_tolerance
        N = range(len(self.W))
        m = self.model = pmo.block()
        x = m.x = pmo.variable_dict()
        y = m.y = pmo.variable_dict()
        for i in N:
            y[i] = pmo.variable(domain=pmo.Binary)
            for j in N:
                x[i,j] = pmo.variable(domain=pmo.Binary)

        m.B = pmo.expression(sum(y.values()))
        m.objective = pmo.objective(m.B, sense=pmo.minimize)

        m.B_nontrivial = pmo.constraint(m.B >= 1)

        m.capacity = pmo.constraint_dict()
        for i in N:
            m.capacity[i] = pmo.constraint(
                sum(x[i,j]*self.W[j] for j in N) <= self.V*y[i])

        m.assign_1 = pmo.constraint_dict()
        for j in N:
            m.assign_1[j] = pmo.constraint(
                sum(x[i,j] for i in N) == 1)

        # relax everything for the bound solves,
        # since the objective uses a simple heuristic
        self.true_domain_type = pmo.ComponentMap()
        for xij in self.model.x.components():
            self.true_domain_type[xij] = xij.domain_type
            xij.domain_type = pmo.RealSet
        for yi in self.model.y.components():
            self.true_domain_type[yi] = yi.domain_type
            yi.domain_type = pmo.RealSet

        self.opt = pmo.SolverFactory(
            pyomo_solver,
            solver_io=pyomo_solver_io)