예제 #1
0
def tw_schedule(time_slot, tasks):
    start_time = time_slot[0]
    end_time = time_slot[1]

    mdl = CpoModel(name="generate_tw")
    # Create model for CP and solve for the first time to obtain initial time windows
    # Decision variables: time interval of each task
    task_vars = {}
    early = lambda x: "task_" + str(x) + "_early"
    late = lambda x: "task_" + str(x) + "_late"
    for id in tasks:
        if tasks[id].exact_time != None:
            # print("exact time: {}".format(tasks[id].exact_time))
            task_vars[early(id)] = mdl.interval_var(start=tasks[id].exact_time,
                                                    size=tasks[id].duration,
                                                    name=early(id))
            task_vars[late(id)] = mdl.interval_var(start=tasks[id].exact_time,
                                                   size=tasks[id].duration,
                                                   name=late(id))
        else:
            task_vars[early(id)] = mdl.interval_var(size=tasks[id].duration,
                                                    name=early(id))
            task_vars[late(id)] = mdl.interval_var(size=tasks[id].duration,
                                                   name=late(id))
    slot = mdl.interval_var(start=start_time,
                            end=end_time)  # Time interval of entire time slot
    # Add Constraints:
    for id in tasks:
        # 1st constraint: all intervals are within start and end time
        mdl.add(mdl.start_before_start(slot, task_vars[early(id)]))
        mdl.add(mdl.end_before_end(task_vars[early(id)], slot))
        mdl.add(mdl.start_before_start(slot, task_vars[late(id)]))
        mdl.add(mdl.end_before_end(task_vars[late(id)], slot))
        # mdl.add(mdl.span(slot, task_vars.values()))

        if tasks[id].precedence_before != []:
            # Tasks that have precedence_before constraints
            # 2nd Constraints: end of precedence_before_task is before start of current task
            for id_before in tasks[id].precedence_before:
                mdl.add(
                    mdl.end_before_start(task_vars[early(id_before)],
                                         task_vars[early(id)]))
                mdl.add(
                    mdl.end_before_start(task_vars[late(id_before)],
                                         task_vars[late(id)]))

    # Add objective:
    obj = mdl.maximize(
        sum([
            mdl.start_of(task_vars[late(id)]) -
            mdl.start_of(task_vars[early(id)]) for id in tasks
        ]))
    mdl.add(obj)

    # Solve model
    # sol = mdl.solve(TimeLimit = 10, LogVerbosity = "Verbose")
    sol = mdl.solve(
        TimeLimit=10,
        LogVerbosity="Quiet",
        agent='local',
        execfile=
        '/Applications/CPLEX_Studio201/cpoptimizer/bin/x86-64_osx/cpoptimizer')
    # sol = mdl.solve()

    if sol:
        # sol.write()
        time_window = {
            id: (sol.get_var_solution(task_vars[early(id)]).get_start(),
                 sol.get_var_solution(task_vars[late(id)]).get_start())
            for id in tasks
        }
    else:
        print("Instance not feasible - earliest start time")
        return {}

    return time_window
예제 #2
0
def main():
    filename = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                            "data_in/test_1.txt")
    inst = instance.Instance(filename)

    # input from master problem, now random
    id_profile = 0
    random.seed(42)
    rewards = [random.randint(0, 30000) for i in range(inst.J)]
    #rewards = [random.uniform(0.0, 30000.0) for i in range(inst.J)]
    equivalences = [[0, 1], [2, 3]]
    mutexes = [[2, 1], [4, 3]]
    # input from master problem, now random

    types = inst.profiles[id_profile]
    types.insert(0, inst.INIT)
    types.append(inst.TERM)
    trans_cost = [[0 for i in range(inst.V)] for j in range(inst.V)]
    trans_time = [[0 for i in range(inst.V)] for j in range(inst.V)]
    for i in range(len(inst.edges)):
        for j in range(len(inst.edges[i])):
            trans_cost[i][inst.edges[i][j][
                'to']] = inst.edges[i][j]['C'] * inst.edges[i][j]['t']
            trans_time[i][inst.edges[i][j]['to']] = inst.edges[i][j]['t']
    changeover_cost = 0
    for i in range(1, len(types)):
        changeover_cost += trans_cost[types[i - 1]][types[i]]

    cp = CpoModel()
    primitives = [[] for i in range(inst.J)]
    all_primitives = []
    init = cp.interval_var(start=0)
    init.set_end_max(inst.L)
    total_cost = changeover_cost + inst.vertices[
        inst.INIT]['C'] * cp.length_of(init, 0)
    modes_of_mach = [init
                     ]  # serves only for retrieving starts and ends of modes
    last_shift = init
    for i in range(1, len(types) - 1):
        v = types[i]
        shift = cp.interval_var()
        shift.set_size_min(inst.vertices[v]['t_min'])
        shift.set_size_max(inst.vertices[v]['t_max'])
        shift.set_end_max(inst.L)
        total_cost += inst.vertices[v]['C'] * cp.length_of(shift, 0)
        cp.add(
            cp.start_at_end(shift, last_shift,
                            -trans_time[types[i - 1]][types[i]]))
        last_shift = shift
        modes_of_mach.append(shift)
        for t in range(inst.J):
            if inst.tasks[t]['p'][v] <= inst.L:
                prim = cp.interval_var(size=inst.tasks[t]['p'][v])
                total_cost -= rewards[t] * cp.presence_of(prim)
                prim.set_optional()
                prim.set_start_min(inst.tasks[t]['r'])
                prim.set_end_max(inst.tasks[t]['d'])
                primitives[t].append(prim)
                all_primitives.append(prim)
                cp.add(cp.start_before_start(shift, prim))
                cp.add(cp.end_before_end(prim, shift))
    term = cp.interval_var(end=inst.L)
    total_cost += inst.vertices[inst.TERM]['C'] * cp.length_of(term, 0)
    cp.add(
        cp.start_at_end(term, last_shift,
                        -trans_time[types[len(types) - 2]][inst.TERM]))
    modes_of_mach.append(term)
    cp.add(cp.no_overlap(cp.sequence_var(all_primitives)))
    for t in range(inst.J):
        cp.add(sum([cp.presence_of(p) for p in primitives[t]]) <= 1)
    for eq in equivalences:
        cp.add(
            sum([cp.presence_of(p) for p in primitives[eq[0]]]) == sum(
                [cp.presence_of(p) for p in primitives[eq[1]]]))
    for mut in mutexes:
        cp.add(
            sum([cp.presence_of(p) for p in primitives[mut[0]]]) +
            sum([cp.presence_of(p) for p in primitives[mut[1]]]) <= 1)
    cp.add(cp.minimize(total_cost))

    # set TimeLimit in seconds or delete it for no limit
    # parameters DefaultInferenceLevel and Workers may be beneficial to add
    sol = cp.solve(
        TimeLimit=30,
        LogVerbosity="Quiet")  #, DefaultInferenceLevel='Extended', Workers=1)
    if sol:
        tasks = []
        for t in range(inst.J):
            for pr in primitives[t]:
                p = sol.get_var_solution(pr)
                if p.is_present():
                    tasks.append({
                        "task": t,
                        "start": p.get_start(),
                        "end": p.get_end()
                    })
                    break
        modes = []
        sched_cost = 0
        for t in range(len(modes_of_mach)):
            m = sol.get_var_solution(modes_of_mach[t])
            modes.append({
                "mode": types[t],
                "start": m.get_start(),
                "end": m.get_end()
            })
            sched_cost += inst.vertices[types[t]]['C'] * m.get_length()
        print("Solution status: " + sol.get_solve_status())
        print("Solve time: " + str(sol.get_solve_time()))
        print("Objective: " + str(sol.get_objective_values()[0]))
        print("Schedule cost: " + str(sched_cost))
        print(tasks)
        print(modes)
    else:
        print("No solution found.")
예제 #3
0
    def init_model(self):
        # INPUTS --------------------------------------------------
        inst = self.instance
        id_profile = self.profile_idx
        rewards = self.l_j
        equivalences = self.on_same
        mutexes = self.on_diff
        # END INPUTS ----------------------------------------------

        # MODEL --------------------------------------------------
        types = list(inst.profiles[id_profile])
        types.insert(0, inst.INIT)
        types.append(inst.TERM)
        trans_time = [[0 for i in range(inst.V)] for j in range(inst.V)]
        for i in range(len(inst.edges)):
            for j in range(len(inst.edges[i])):
                trans_time[i][inst.edges[i][j]['to']] = inst.edges[i][j]['t']
        changeover_cost = inst.get_trans_cost(id_profile)

        cp = CpoModel()
        """
        primitives = [[] for i in range(inst.J)]
        all_primitives = []
        init = cp.interval_var(start=0)
        init.set_end_max(inst.L)
        total_cost = changeover_cost + inst.vertices[inst.INIT]['C'] * cp.length_of(init, 0) - self.l_0  # subtract l_0
        modes_of_mach = [init]  # serves only for retrieving starts and ends of modes
        last_shift = init
        for i in range(1, len(types) - 1):
            v = types[i]
            shift = cp.interval_var()
            shift.set_size_min(inst.vertices[v]['t_min'])
            shift.set_size_max(inst.vertices[v]['t_max'])
            shift.set_end_max(inst.L)
            total_cost += inst.vertices[v]['C'] * cp.length_of(shift, 0)
            cp.add(cp.start_at_end(shift, last_shift, -trans_time[types[i - 1]][types[i]]))
            last_shift = shift
            modes_of_mach.append(shift)
            for t in range(inst.J):
                if inst.tasks[t]['p'][v] <= inst.L:
                    prim = cp.interval_var(size=inst.tasks[t]['p'][v])
                    total_cost -= rewards[t] * cp.presence_of(prim)
                    prim.set_optional()
                    prim.set_start_min(inst.tasks[t]['r'])
                    prim.set_end_max(inst.tasks[t]['d'])
                    primitives[t].append(prim)
                    all_primitives.append(prim)
                    cp.add(cp.start_before_start(shift, prim))
                    cp.add(cp.end_before_end(prim, shift))
        term = cp.interval_var(end=inst.L)
        total_cost += inst.vertices[inst.TERM]['C'] * cp.length_of(term, 0)
        cp.add(cp.start_at_end(term, last_shift, -trans_time[types[len(types) - 2]][inst.TERM]))
        modes_of_mach.append(term)
        cp.add(cp.no_overlap(cp.sequence_var(all_primitives)))
        for t in range(inst.J):
            cp.add(sum([cp.presence_of(p) for p in primitives[t]]) <= 1)
        for eq in equivalences:
            cp.add(sum([cp.presence_of(p) for p in primitives[eq[0]]]) == sum(
                [cp.presence_of(p) for p in primitives[eq[1]]]))
        for mut in mutexes:
            cp.add(sum([cp.presence_of(p) for p in primitives[mut[0]]]) + sum(
                [cp.presence_of(p) for p in primitives[mut[1]]]) <= 1)
        """
        #"""
        # MODEL 2
        primitives = [[] for i in range(inst.J)]
        all_primitives = []
        init = cp.interval_var(start=0)
        init.set_end_max(inst.L)
        total_cost = changeover_cost + inst.vertices[
            inst.INIT]['C'] * cp.length_of(init, 0) - self.l_0
        modes_of_mach = [
            init
        ]  # serves only for retrieving starts and ends of modes
        last_shift = init
        for i in range(1, len(types) - 1):
            v = types[i]
            shift = cp.interval_var()
            shift.set_size_min(inst.vertices[v]['t_min'])
            shift.set_size_max(inst.vertices[v]['t_max'])
            shift.set_end_max(inst.L)
            total_cost += inst.vertices[v]['C'] * cp.length_of(shift, 0)
            cp.add(
                cp.start_at_end(shift, last_shift,
                                -trans_time[types[i - 1]][types[i]]))
            last_shift = shift
            modes_of_mach.append(shift)
            sub_tasks = []
            for t in range(inst.J):
                if inst.tasks[t]['p'][v] <= inst.L:
                    prim = cp.interval_var(size=inst.tasks[t]['p'][v])
                    total_cost -= rewards[t] * cp.presence_of(prim)
                    prim.set_optional()
                    prim.set_start_min(inst.tasks[t]['r'])
                    prim.set_end_max(inst.tasks[t]['d'])
                    primitives[t].append(prim)
                    sub_tasks.append(prim)
                    cp.add(cp.start_before_start(shift, prim))
                    cp.add(cp.end_before_end(prim, shift))
            if len(sub_tasks) > 1:
                cp.add(cp.no_overlap(cp.sequence_var(sub_tasks)))
        term = cp.interval_var(end=inst.L)
        total_cost += inst.vertices[inst.TERM]['C'] * cp.length_of(term, 0)
        cp.add(
            cp.start_at_end(term, last_shift,
                            -trans_time[types[len(types) - 2]][inst.TERM]))
        modes_of_mach.append(term)
        for t in range(inst.J):
            cp.add(sum([cp.presence_of(p) for p in primitives[t]]) <= 1)
        for eq in equivalences:
            cp.add(
                sum([cp.presence_of(p) for p in primitives[eq[0]]]) == sum(
                    [cp.presence_of(p) for p in primitives[eq[1]]]))
        for mut in mutexes:
            cp.add(
                sum([cp.presence_of(p) for p in primitives[mut[0]]]) +
                sum([cp.presence_of(p) for p in primitives[mut[1]]]) <= 1)
        #"""
        """
        # MOdel 3
        primitives = [[] for i in range(inst.J)]
        init = cp.interval_var(start=0)
        init.set_end_max(inst.L)
        total_cost = changeover_cost + inst.vertices[inst.INIT]['C'] * cp.length_of(init, 0) - self.l_0
        modes_of_mach = [init]  # serves only for retrieving starts and ends of modes
        last_shift = init
        for i in range(1, len(types) - 1):
            v = types[i]
            shift = cp.interval_var()
            shift.set_size_min(inst.vertices[v]['t_min'])
            shift.set_size_max(inst.vertices[v]['t_max'])
            shift.set_end_max(inst.L)
            total_cost += inst.vertices[v]['C'] * cp.length_of(shift, 0)
            cp.add(cp.start_at_end(shift, last_shift, -trans_time[types[i - 1]][types[i]]))
            last_shift = shift
            modes_of_mach.append(shift)
            for t in range(inst.J):
                if inst.tasks[t]['p'][v] <= inst.L:
                    prim = cp.interval_var(size=inst.tasks[t]['p'][v])
                    prim.set_optional()
                    prim.set_start_min(inst.tasks[t]['r'])
                    prim.set_end_max(inst.tasks[t]['d'])
                    primitives[t].append(prim)
                    cp.add(cp.start_before_start(shift, prim))
                    cp.add(cp.end_before_end(prim, shift))
        term = cp.interval_var(end=inst.L)
        total_cost += inst.vertices[inst.TERM]['C'] * cp.length_of(term, 0)
        cp.add(cp.start_at_end(term, last_shift, -trans_time[types[len(types) - 2]][inst.TERM]))
        modes_of_mach.append(term)
        masters = []
        for t in range(inst.J):
            new_master = cp.interval_var()
            new_master.set_optional()
            masters.append(new_master)
            total_cost -= rewards[t] * cp.presence_of(new_master)
            cp.add(cp.alternative(new_master, primitives[t]))
        cp.add(cp.no_overlap(cp.sequence_var(masters)))
        for eq in equivalences:
            cp.add(cp.presence_of(masters[eq[0]]) == cp.presence_of(masters[eq[1]]))
        for mut in mutexes:
            cp.add(cp.presence_of(masters[mut[0]]) + cp.presence_of(masters[mut[1]]) <= 1)
        """
        cp.add(cp.minimize(total_cost))

        # Set self.model
        self.model = cp
        self.primitives = primitives
        self.modes_of_mach = modes_of_mach
        self.types = types