def _create_model(self, job_ids, r_times, p_intervals, m_availabe): ## prepare the index for decision variables # start time of process jobs = tuple(job_ids) machines = tuple(range(len(machine_properties))) # order of executing jobs: tuple list jobPairs = [(i, j) for i in jobs for j in jobs if i < j] # assignment of jobs on machines job_machinePairs = [(i, k) for i in jobs for k in machines] ## parameters model (dictionary) # 1. release time release_time = dict(zip(jobs, tuple(r_times))) # 2. process time process_time = dict(zip(jobs, tuple(p_intervals))) # 3. machiane available time machine_time = dict(zip(machines, tuple(m_availabe))) # 4. define BigM BigM = np.sum(r_times) + np.sum(p_intervals) + np.sum(m_availabe) ## create model m = Model('PMSP') ## create decision variables # 1. assignments of jobs on machines z = m.addVars(job_machinePairs, vtype=GRB.BINARY, name='assign') # 2. order of executing jobs y = m.addVars(jobPairs, vtype=GRB.BINARY, name='order') # 3. start time of executing each job startTime = m.addVars(jobs, name='startTime') ## create objective # m.setObjective(quicksum(startTime), GRB.MINIMIZE) # TOTRY m._max_complete = m.addVar(1, name='max_complete_time') m.setObjective(m._max_complete, GRB.MINIMIZE) # TOTRY m.addConstr((m._max_complete == max_(startTime)), 'minimax') ## create constraints # 1. job release constraint m.addConstrs((startTime[i] >= release_time[i] for i in jobs), 'job release constraint') # 2. machine available constraint m.addConstrs((startTime[i] >= machine_time[k] - BigM * (1 - z[i, k]) for (i, k) in job_machinePairs), 'machine available constraint') # 3. disjunctive constraint m.addConstrs((startTime[j] >= startTime[i] + process_time[i] - BigM * ((1 - y[i, j]) + (1 - z[j, k]) + (1 - z[i, k])) for k in machines for (i, j) in jobPairs), 'temporal disjunctive order1') m.addConstrs((startTime[i] >= startTime[j] + process_time[j] - BigM * (y[i, j] + (1 - z[j, k]) + (1 - z[i, k])) for k in machines for (i, j) in jobPairs), 'temporal disjunctive order2') # 4. one job is assigned to one and only one machine m.addConstrs((quicksum([z[i, k] for k in machines]) == 1 for i in jobs), 'job non-splitting') # set initial solution for (i, k) in job_machinePairs: if (i, k) in assign_list: z[(i, k)].start = 1 else: z[(i, k)].start = 0 for (i, j) in jobPairs: if (i, j) in order_list: y[(i, j)].start = 1 else: y[(i, j)].start = 0 for i in job_ids: startTime[i].start = start_times[i] return m, z, y, startTime
def _create_model(self, job_ids, r_times, p_intervals, m_availabe, SRPT_MAX): ## prepare the index for decision variables # start time of process jobs = tuple(job_ids) machines = tuple(range(len(machine_properties))) # define BigM # BigM = np.sum(r_times) + np.sum(p_intervals) + np.sum(m_availabe) # BigM = np.max(r_times) + np.max(p_intervals) # define possible largest time duration # TIME = range(int(BigM)) TIME = range(int(SRPT_MAX)) ## parameters model (dictionary) # 1. release time release_time = dict(zip(jobs, tuple(r_times))) # 2. process time process_time = dict(zip(jobs, tuple(p_intervals))) # 3. machiane available time machine_time = dict(zip(machines, tuple(m_availabe))) ## create model m = Model('PMSP') # job machine time m._MachineJobTime = [(k,j,t) for k in machines for j in jobs for t in TIME] ## create decision variables m._max_complete = m.addVar(1, name='max_complete_time') # 1. Chi: job j is processed on Machine i and processed at time t m._CHI = m.addVars(m._MachineJobTime, vtype=GRB.BINARY, name='order') # 2. complete time of executing each job m._completeTime = m.addVars(jobs, name='completeTime') ## create objective m.setObjective(quicksum(m._completeTime), GRB.MINIMIZE) # TOTRY # m.setObjective(m._max_complete, GRB.MINIMIZE) # TOTRY ## create constraints # 1. Each job starts processing on only one machine at only one point in time for j in jobs: expr = 0 for k in machines: for t in TIME: expr += m._CHI[k,j,t] m.addConstr((expr == 1), 'time nonsplitting') m.update() # m.addConstrs((quicksum([m._CHI[k,i,t] for k in machines for t in TIME])==1 for i in jobs),'job machine match') # 2. At most one job is processed at any time on any machine for k in machines: for t in TIME[1:]: expr = 0 for j_id in jobs: h = max(0, t - process_time[j_id]) for t_id in range(h, t): expr += m._CHI[k,j_id,t_id] m.addConstr(expr <= 1) m.update() # 3. Completion time requirement # m.addConstrs((quicksum([(t+process_time[j]+machine_time[i])*m._CHI[i,j,t] for i in machines for t in TIME]) <= m._completeTime[j] for j in jobs), "CT") for j in jobs: expr = 0 for i in machines: for t in TIME: expr += (t + process_time[j])*m._CHI[i,j,t] m.addConstr(expr == m._completeTime[j]) m.update() # 4. release time constraint # m.addConstrs((quicksum([m._CHI[i,j_id,t] for i in machines for t in range(release_time[j_id])])==0 for j_id in jobs if release_time[j_id]>0),'release') for j in jobs: if release_time[j] > 0: expr = 0 for i in machines: for t in range(release_time[j]): expr += m._CHI[i,j,t] m.addConstr(expr==0) m.update() # 5. machine available time # m.addConstrs((quicksum([m._CHI[m_id,j,t] for j in jobs for t in range(machine_time[m_id])])==0 for m_id in machines if machine_time[m_id]>0),'available') for i in machines: if machine_time[i]>0: expr = 0 for j in jobs: for t in range(machine_time[i]): expr += m._CHI[i,j,t] m.addConstr(expr== 0) m.update() # 6. for minimax m.addConstrs((m._max_complete>=m._completeTime[j] for j in jobs),'minimax') return m