# Phase 1 # # Cost of tasks is calculated here without concerning ourselves # about the machine costs. task_intervals_on_machines = {m['id']: [] for m in data['machines']} task_intervals = [] for machine in data['machines']: m_id = machine['id'] # Sequencing of intervals num_intervals = len(on_intervals[m_id]) for i in range(1, num_intervals): model.add( model.if_then(model.presence_of(on_intervals[m_id][i]), model.presence_of(on_intervals[m_id][i - 1]))) model.add( model.end_before_start(on_intervals[m_id][i - 1], on_intervals[m_id][i], 1)) # Bind with task intervals for on_i in on_intervals[m_id]: machine_on_off[m_id] += model.pulse(on_i, 1) model.add( model.always_constant(tasks_running_on_machines[m_id], on_i, True, True)) for task in data['tasks']: # Master task interval task_interval = model.interval_var( size=task['duration'],
def CP_model_restricted(params): ## NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, ITEM_SIZES, COLORS, NUM_BINS, Timelimit, SEED = params mdl = CpoModel() X = [mdl.integer_var(min=0, max=NUM_BINS) for item in range(NUM_ITEMS)] CP = mdl.integer_var_list(NUM_BINS, min=0, max=BIN_SIZE) for bin in range(NUM_BINS - 1): mdl.add(CP[bin] >= CP[bin + 1]) mdl.add(pack(CP, [X[item] for item in range(NUM_ITEMS)], ITEM_SIZES)) CC = [ mdl.integer_var_list(NUM_COLORS, min=0, max=BIN_SIZE) for bin in range(NUM_BINS) ] for color in range(NUM_COLORS): mdl.add( distribute([CC[bin][color] for bin in range(NUM_BINS)], [ X[item] for item in range(NUM_ITEMS) if COLORS[item] == color ], [bin for bin in range(NUM_BINS)])) for bin in range(NUM_BINS): TC = mdl.sum(CC[bin]) MC = mdl.max(CC[bin]) # mdl.add_kpi(TC, name="TC_{}".format(bin)) # mdl.add_kpi(MC, name="MC_{}".format(bin)) # mdl.add( # (TC+mdl.mod(TC, 2))/2 >= MC # # ) # mdl.add( # (TC - mdl.mod(TC, NUM_COLORS))/NUM_COLORS >= MC # ) # mdl.add( # mdl.sum( # CC[bin][color] > 0 for color in range(NUM_COLORS) # ) <= MAX_COLORS_IN_BIN # ) for item in range(NUM_ITEMS): for item2 in range(item + 1, NUM_ITEMS): if COLORS[item] == COLORS[item2]: mdl.add( mdl.if_then( X[item] == X[item2], mdl.any([ X[i] == X[item] for i in range(item + 1, item2 + 1) if COLORS[i] != COLORS[item] ]) # mdl.count([mdl.element(COLORS, i) for i in range(item, item2+1)], abs(COLORS[item] -1)) > 0 )) # mdl.add( # mdl.minimize(count_different(X)) # ) # bins_used = mdl.sum(CP[bin] > 0 for bin in range(NUM_BINS)) # mdl.add( # mdl.minimize( # bins_used # ) # ) mdl.add(mdl.minimize(mdl.max(X) + 1)) try: msol = mdl.solve(TimeLimit=20) mdl._myInstance = (NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED) # # print(ITEM_SIZES) # print(COLORS) # # print([msol[X[item]] for item in range(NUM_ITEMS)]) Xs = np.array([msol[X[i]] for i in range(NUM_ITEMS)]) if solution_checker(Xs, COLORS, ITEM_SIZES, BIN_SIZE, SEED, 'restricted_cp_binary'): write_to_global_cp(msol, mdl, 'restricted_binary') except Exception as err: print(err) write_to_global_failed(NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED, 'restricted_cp_binary', is_bad_solution=False)
visit must be done, among all days of the scheduling horizon. sum over l (x_{k,i,j}^{l} + y_{k,i,j}^{l} <= 1) ; \forall (k, i, j) (2) If a patient is admitted, all his/her visit sessions must be done. Hence, only if z_i == 1 the constraint above must hold It's possible to manually force an admittance to happen, if it has waited long enough, just by setting z_i=1 for patient i. ''' for pat in patient_list: # i for doc in pat.visit_vars_dict: # k nb_doc_sessions = len(pat.visit_vars_dict[doc]) # j for j in range(nb_doc_sessions): cons = mdl.if_then( pat.is_admitted_var == 1, mdl.sum(pat.visit_vars_dict[doc][j].x_vars[l] + pat.visit_vars_dict[doc][j].y_vars[l] for l in range(pat.nb_visit_days)) == 1) # print(cons) mdl.add(cons) ''' CONSTRAINT: For the same patient and doctor, at least some visit sessions must happen in the morning. This is because children become tired in the afternoon, and harder to work with, which makes it more difficult for the doctor to conduct diagnosis. Hence each doctor wants to do at least some visits of the same patient in the morning. sum_sum_j_l( y_{k,i,j}^{l}) <= sum_sum_j_l(x_{k,i,j}^{l}) + 1 ; \forall (k, i) ''' for pat in patient_list: # i
tvar = toIndex[m] fromState = states[m] toState = states[m + 1] # Constrain location of holes mdl.add(mdl.element(fromState, tvar) == HOLE) # Constrain move size and direction delta = tvar - fvar mdl.add(mdl.allowed_assignments(delta, [-2, -1, 1, 2])) peg = mdl.element(fromState, fvar) mdl.add( ((peg == RED) & (delta > 0)) | ((peg == BLUE) & (delta < 0)) ) # Make moves mdl.add(mdl.element(toState, tvar) == mdl.element(fromState, fvar)) mdl.add(mdl.element(toState, fvar) == HOLE) # Force equality of other positions for p in range(SIZE): mdl.add(mdl.if_then((p != fvar) & (p != tvar), fromState[p] == toState[p])) # Set initial position for p in range(NB_PEGS): mdl.add(states[0][p] == RED) mdl.add(states[0][p + NB_PEGS + 1] == BLUE) mdl.add(states[0][NB_PEGS] == HOLE) # Force last state to be final expr = states[NB_MOVES][NB_PEGS] == HOLE for p in range(NB_PEGS): expr &= states[NB_MOVES][p] == BLUE expr &= states[NB_MOVES][p + NB_PEGS + 1] == RED mdl.add(expr)
Result.append(mass[i_use2][j]) return Result def get_or_on_neigh(neigh): if len(neigh) == 2: return (mdl.equal(neigh[0],0) | mdl.equal(neigh[1],0)) elif len(neigh) == 3: return (mdl.equal(neigh[0],0) | mdl.equal(neigh[1],0) | mdl.equal(neigh[2],0)) elif len(neigh) == 4: return (mdl.equal(neigh[0],0) | mdl.equal(neigh[1],0) | mdl.equal(neigh[2],0) | mdl.equal(neigh[3],0)) else: raise IndexError('Что-то пошло не так') for i in range(SIZE_X): for j in range(SIZE_Y): neigh = get_neigh(mass_v, i, j) expr = mdl.if_then(mdl.equal(mass_v[i][j],1), get_or_on_neigh(neigh)) mdl.add(expr) def get_neighbours_with_checked(mass, i, j, checked): Y_SIZE = len(mass[0]) X_SIZE = len(mass) Result = [] i_use1 = i + 1 j_use1 = j + 1 i_use2 = i - 1 j_use2 = j - 1 if i - 1 < 0: i_use2 = i + 1 if i + 1 >= X_SIZE: i_use1 = i - 1 if j + 1 >= Y_SIZE: