Beispiel #1
0
    def _cut(self, model, val_func, cut_func):
        '''Returns true if a cut was added to the master'''
        problem = self.problem
        theta = self.theta
        x = self.x

        # Create subproblem.
        sub = Model()

        # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage
        #                s by running command c during s, 0 otherwise
        y = {}
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s, c in product(problem.shared_stages[ip, iq], cmds):
                y[ip, iq, s,
                  c] = sub.addVar(name='y[%s,%s,%s,%s]' % (ip, iq, s, c))

        sub.update()

        # Find shared paths among image pairs.
        constraints = defaultdict(list)
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s in problem.shared_stages[ip, iq]:
                for c in cmds:
                    constraints[ip, s, c].append(
                        sub.addConstr(
                            y[ip, iq, s, c] <= val_func(model, x[ip, s, c])))
                    constraints[iq, s, c].append(
                        sub.addConstr(
                            y[ip, iq, s, c] <= val_func(model, x[iq, s, c])))
                if s > 1:
                    sub.addConstr(
                        sum(y[ip, iq, s, c]
                            for c in cmds) <= sum(y[ip, iq, s - 1, c]
                                                  for c in cmds))

        sub.setObjective(
            -sum(problem.commands[c] * y[ip, iq, s, c] for ip, iq, s, c in y),
            GRB.MINIMIZE)
        sub.optimize()

        # Add the dual prices for each variable
        pi = defaultdict(float)
        for isp, cons in constraints.iteritems():
            for c in cons:
                pi[isp] += c.pi

        # Detect optimality
        if val_func(model, theta) >= sub.objVal:
            return False  # no cuts to add

        # Optimality cut
        cut_func(model,
                 theta >= sum(pi[isp] * x[isp] for isp in pi if pi[isp]))
        return True
Beispiel #2
0
    def solve(self, problem, saver):
        # Construct model.
        self.problem = problem

        # Do recursive maximal clique detection.
        self.clique_data = clique_data = problem.cliques()
        self.model = model = Model()
        if self.time is not None:
            model.params.TimeLimit = 60 * int(self.time)

        # Each image needs to run all its commands. This keep track of
        # what variables run each command for each image.
        self.by_img_cmd = by_img_cmd = defaultdict(list)

        # Objective is the total cost of all the commands we run.
        self._obj = []

        # x[i,c] = 1 if image i incurs the cost of command c directly
        self.x = x = {}
        for img, cmds in problem.images.items():
            for cmd in cmds:
                name = 'x[%s,%s]' % (img, cmd)
                x[name] = v = model.addVar(vtype=GRB.BINARY, name=name)
                self._obj.append(problem.commands[cmd] * v)
                by_img_cmd[img, cmd].append(v)

        # cliques[i] = 1 if clique i is used, 0 otherwise
        self.cliques = {}
        self._update(clique_data)

        for c in clique_data['cliques']:
            print c
        # Each image has to run each of its commands.
        for img_cmd, vlist in by_img_cmd.items():
            self.model.addConstr(sum(vlist) == 1)

        model.setObjective(sum(self._obj), GRB.MINIMIZE)
        model.optimize()  # lambda *args: self._callback(saver, *args))

        # TODO: callback
        # Translate the output of this to a schedule.
        schedule = defaultdict(list)
        self._translate(schedule, clique_data)
        for name, v in x.items():
            img, cmd = name.replace('x[', '').replace(']', '').split(',')
            if v.x > 0.5:
                schedule[img].append(cmd)
        saver(schedule)
    def _cut(self, model, val_func, cut_func):
        '''Returns true if a cut was added to the master'''
        problem = self.problem
        theta = self.theta
        x = self.x

        # Create subproblem.
        sub = Model()

        # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage
        #                s by running command c during s, 0 otherwise
        y = {}
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s, c in product(problem.shared_stages[ip, iq], cmds):
                y[ip,iq,s,c] = sub.addVar(name='y[%s,%s,%s,%s]' % (ip,iq,s,c))

        sub.update()

        # Find shared paths among image pairs.
        constraints = defaultdict(list)
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s in problem.shared_stages[ip,iq]:
                for c in cmds:
                    constraints[ip,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[ip,s,c])))
                    constraints[iq,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[iq,s,c])))
                if s > 1:
                    sub.addConstr(sum(y[ip,iq,s,c] for c in cmds) <= sum(y[ip,iq,s-1,c] for c in cmds))

        sub.setObjective(
            -sum(problem.commands[c] * y[ip,iq,s,c] for ip,iq,s,c in y),
            GRB.MINIMIZE
        )
        sub.optimize()

        # Add the dual prices for each variable
        pi = defaultdict(float)
        for isp, cons in constraints.iteritems():
            for c in cons:
                pi[isp] += c.pi

        # Detect optimality
        if val_func(model, theta) >= sub.objVal:
            return False # no cuts to add

        # Optimality cut
        cut_func(model, theta >= sum(pi[isp]*x[isp] for isp in pi if pi[isp]))
        return True
Beispiel #4
0
    def _update(self, clique_data, parent=None):
        for c in clique_data['cliques']:
            self.cliques[c['name']] = v = self.model.addVar(
                vtype=GRB.BINARY,
                name=c['name']
            )
            self.model.update()

            for img, cmd in product(c['images'], c['commands']):
                self.by_img_cmd[img, cmd].append(v)

            self._obj.append(c['time'] * v)

            if parent is not None:
                self.model.addConstr(v <= self.cliques[parent['name']])

            for child in c['children']:
                self._update(child, c)

        for inter in clique_data['intersections']:
            self.model.addConstr(sum(self.cliques[i] for i in inter) <= 1)
Beispiel #5
0
    [10,  6, 12],
    [ 8,  4, 15],
    [ 6, 12,  5]
]

# x[i][j] = 1 if i is assigned to j
x = []
for i in range(len(c)):
    x_i = []
    for j in c[i]:
        x_i.append(model.addVar(vtype=GRB.BINARY))
    x.append(x_i)

# sum <j> x_ij <= 1 for all i
for x_i in x:
    model.addLRConstr(sum(x_i) <= 1)

# sum <i> a_ij * x_ij <= b[j] for all j
for j in range(len(b)):
    model.addConstr(sum(a[i][j] * x[i][j] for i in range(len(x))) <= b[j])

# max sum <i,j> c_ij * x_ij
model.setObjective(
    sum(
        sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i))
        for c_i, x_i in zip(c, x)
    )
)

model.LRoptimize(debug=True)
    def solve(self, problem, saver):
        # TODO: time limits
        # TODO: symmetry?

        # Construct master model.
        self.problem = problem
        self.model = model = Model()
        model.params.LazyConstraints = 1

        self.theta = theta = model.addVar(lb=-GRB.INFINITY, name='theta')

        # x[i,s,c] = 1 if image i runs command c during stage s, 0 otherwise
        self.x = x = {}
        for i, cmds in problem.images.items():
            for s, c in product(problem.stages[i], cmds):
                x[i,s,c] = model.addVar(vtype=GRB.BINARY, name='x[%s,%s,%s]' % (i,s,c))

        model.update()

        # Need to reference vars by their indices later.
        self.xind = {xvar: isc for isc, xvar in x.items()}

        # Each image one command per stage, and each command once.
        for i in problem.images:
            for s in problem.stages[i]:
                model.addConstr(sum(x[i,s,c] for c in problem.images[i]) == 1)
            for c in problem.images[i]:
                model.addConstr(sum(x[i,s,c] for s in problem.stages[i]) == 1)

        model.setObjective(theta, GRB.MINIMIZE)

        # Optimize until we can longer add optimality cuts.
        iteration = 1
        while True:
            if iteration == 1:
                # Use heuristic for initial feasible solution.
                soln = []
                def save_initial(schedule):
                    soln.append(schedule)
                MostCommonHeuristic().solve(problem, save_initial)
                init = soln.pop()

                # Inform the master model of this solution.
                for i,s,c in x:
                    if init[i][s-1] == c:
                        x[i,s,c].start = 1

                def val_func(m, xvar):
                    if xvar is theta:
                        return -GRB.INFINITY

                    i,s,c = self.xind[xvar]
                    if init[i][s-1] == c:
                        return 1
                    else:
                        return 0

            else:
                model.optimize(lambda *args: self._callback(saver, *args))
                val_func = lambda m, xvar: xvar.x

            cut_func = lambda m, cons: m.addConstr(cons)
            saver(self._schedule(val_func))

            if not self._cut(model, val_func, cut_func):
                break

            iteration += 1

        saver(self._schedule(val_func))
    def solve(self, problem, saver):
        # Construct model.
        self.problem = problem
        self.model = model = Model()
        if self.time is not None:
            model.params.TimeLimit = 60 * int(self.time)

        # x[i,s,c] = 1 if image i runs command c during stage s, 0 otherwise.
        self.x = x = {}
        for i, cmds in problem.images.items():
            for s, c in product(problem.stages[i], cmds):
                x[i, s, c] = model.addVar(vtype=GRB.BINARY, name="x[%s,%s,%s]" % (i, s, c))

        # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage
        #                s by running command c during s, 0 otherwise.
        y = {}
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s, c in product(problem.shared_stages[ip, iq], cmds):
                y[ip, iq, s, c] = model.addVar(vtype=GRB.BINARY, name="y[%s,%s,%s,%s]" % (ip, iq, s, c))

        model.update()

        # TODO: need to remove presolved commands so the heuristic doesn't try them.

        # Add a heuristic initial solution.
        if self.heur is not None:
            self._heur()

        # Presolving
        if self.presol in ("all", "unshared"):
            self._presol_unshared()
        if self.presol in ("all", "shared"):
            self._presol_shared()

        # Each image one command per stage, and each command once.
        for i in problem.images:
            for s in problem.stages[i]:
                model.addConstr(sum(x[i, s, c] for c in problem.images[i]) == 1)
            for c in problem.images[i]:
                model.addConstr(sum(x[i, s, c] for s in problem.stages[i]) == 1)

        # Find shared paths among image pairs.
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s in problem.shared_stages[ip, iq]:
                for c in cmds:
                    model.addConstr(y[ip, iq, s, c] <= x[ip, s, c])
                    model.addConstr(y[ip, iq, s, c] <= x[iq, s, c])
                if s > 1:
                    model.addConstr(sum(y[ip, iq, s, c] for c in cmds) <= sum(y[ip, iq, s - 1, c] for c in cmds))

        model.setObjective(sum(problem.commands[c] * y[ip, iq, s, c] for ip, iq, s, c in y), GRB.MAXIMIZE)
        model.optimize(lambda *args: self._callback(saver, *args))

        # Create optimal schedule.
        schedule = defaultdict(list)
        for i, stages in problem.stages.items():
            for s in stages:
                for c in problem.images[i]:
                    if x[i, s, c].x > 0.5:
                        schedule[i].append(c)
                        break

        saver(schedule)
Beispiel #8
0
    def solve(self, problem, saver):
        # Construct model.
        self.problem = problem
        self.model = model = Model()
        if self.time is not None:
            model.params.TimeLimit = 60 * int(self.time)

        # x[i,s,c] = 1 if image i runs command c during stage s, 0 otherwise.
        self.x = x = {}
        for i, cmds in problem.images.items():
            for s, c in product(problem.stages[i], cmds):
                x[i, s, c] = model.addVar(vtype=GRB.BINARY,
                                          name='x[%s,%s,%s]' % (i, s, c))

        # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage
        #                s by running command c during s, 0 otherwise.
        y = {}
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s, c in product(problem.shared_stages[ip, iq], cmds):
                y[ip, iq, s,
                  c] = model.addVar(vtype=GRB.BINARY,
                                    name='y[%s,%s,%s,%s]' % (ip, iq, s, c))

        model.update()

        # TODO: need to remove presolved commands so the heuristic doesn't try them.

        # Add a heuristic initial solution.
        if self.heur is not None:
            self._heur()

        # Presolving
        if self.presol in ('all', 'unshared'):
            self._presol_unshared()
        if self.presol in ('all', 'shared'):
            self._presol_shared()

        # Each image one command per stage, and each command once.
        for i in problem.images:
            for s in problem.stages[i]:
                model.addConstr(
                    sum(x[i, s, c] for c in problem.images[i]) == 1)
            for c in problem.images[i]:
                model.addConstr(
                    sum(x[i, s, c] for s in problem.stages[i]) == 1)

        # Find shared paths among image pairs.
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s in problem.shared_stages[ip, iq]:
                for c in cmds:
                    model.addConstr(y[ip, iq, s, c] <= x[ip, s, c])
                    model.addConstr(y[ip, iq, s, c] <= x[iq, s, c])
                if s > 1:
                    model.addConstr(
                        sum(y[ip, iq, s, c]
                            for c in cmds) <= sum(y[ip, iq, s - 1, c]
                                                  for c in cmds))

        model.setObjective(
            sum(problem.commands[c] * y[ip, iq, s, c] for ip, iq, s, c in y),
            GRB.MAXIMIZE)
        model.optimize(lambda *args: self._callback(saver, *args))

        # Create optimal schedule.
        schedule = defaultdict(list)
        for i, stages in problem.stages.items():
            for s in stages:
                for c in problem.images[i]:
                    if x[i, s, c].x > 0.5:
                        schedule[i].append(c)
                        break

        saver(schedule)
Beispiel #9
0
    def solve(self, problem, saver):
        # TODO: time limits
        # TODO: symmetry?

        # Construct master model.
        self.problem = problem
        self.model = model = Model()
        model.params.LazyConstraints = 1

        self.theta = theta = model.addVar(lb=-GRB.INFINITY, name='theta')

        # x[i,s,c] = 1 if image i runs command c during stage s, 0 otherwise
        self.x = x = {}
        for i, cmds in problem.images.items():
            for s, c in product(problem.stages[i], cmds):
                x[i, s, c] = model.addVar(vtype=GRB.BINARY,
                                          name='x[%s,%s,%s]' % (i, s, c))

        model.update()

        # Need to reference vars by their indices later.
        self.xind = {xvar: isc for isc, xvar in x.items()}

        # Each image one command per stage, and each command once.
        for i in problem.images:
            for s in problem.stages[i]:
                model.addConstr(
                    sum(x[i, s, c] for c in problem.images[i]) == 1)
            for c in problem.images[i]:
                model.addConstr(
                    sum(x[i, s, c] for s in problem.stages[i]) == 1)

        model.setObjective(theta, GRB.MINIMIZE)

        # Optimize until we can longer add optimality cuts.
        iteration = 1
        while True:
            if iteration == 1:
                # Use heuristic for initial feasible solution.
                soln = []

                def save_initial(schedule):
                    soln.append(schedule)

                MostCommonHeuristic().solve(problem, save_initial)
                init = soln.pop()

                # Inform the master model of this solution.
                for i, s, c in x:
                    if init[i][s - 1] == c:
                        x[i, s, c].start = 1

                def val_func(m, xvar):
                    if xvar is theta:
                        return -GRB.INFINITY

                    i, s, c = self.xind[xvar]
                    if init[i][s - 1] == c:
                        return 1
                    else:
                        return 0

            else:
                model.optimize(lambda *args: self._callback(saver, *args))
                val_func = lambda m, xvar: xvar.x

            cut_func = lambda m, cons: m.addConstr(cons)
            saver(self._schedule(val_func))

            if not self._cut(model, val_func, cut_func):
                break

            iteration += 1

        saver(self._schedule(val_func))