Beispiel #1
0
    def __init__(self, problem):
        # Problem
        self.problem = problem

        # Utilities

        self.num_weeks = len(problem.weeks)
        self.num_days = len(problem.working_days)

        self.num_doctors = len(problem.doctors)
        self.num_areas = len(problem.areas)
        self.num_schedules = len(problem.schedules)
        self.num_versions = len(problem.versions)
        self.schedule_versions = [
            x * self.num_schedules + y for x in problem.schedules
            for y in problem.versions
        ]
        self.num_schedule_versions = self.num_schedules * self.num_versions

        all_schedule_versions = range(self.num_schedule_versions)
        all_doctors = range(self.num_doctors)
        all_weeks = range(self.num_weeks)
        all_days = range(self.num_days)
        all_versions = range(self.num_versions)
        all_areas = range(self.num_areas)
        all_schedules = range(self.num_schedules)

        self.model = cp_model.CpModel()

        # build all the possible permutations including the specialties
        self.assignment = {}
        for sv in all_schedule_versions:
            for w in all_weeks:
                for a in all_areas:
                    for d in all_doctors:
                        for day in all_days:
                            if d in self.problem.specialties[a]:
                                name = 'C:{%i} W:{%i} S:{%i} T:{%i} Slot:{%i}' % (
                                    sv, w, a, d, day)
                                # print(name)
                                self.assignment[sv, w, a, d,
                                                day] = self.model.NewBoolVar(
                                                    name)
                            else:
                                name = 'NO DISP C:{%i} W:{%i} S:{%i} T:{%i} Slot:{%i}' % (
                                    sv, w, a, d, day)
                                # print(name)
                                self.assignment[sv, w, a, d,
                                                day] = self.model.NewIntVar(
                                                    0, 0, name)

        # Constraints

        # Each schedule/version must have the quantity of areas specified in the curriculum
        # 8/15: All areas are required 5 days of the week
        for sch in all_schedules:
            for ver in all_versions:
                sch_ver = sch * self.num_versions + ver
                for week in all_weeks:
                    for area in all_areas:
                        required_days = self.problem.curriculum[
                            self.problem.schedules[sch],
                            self.problem.areas[area]]
                        self.model.Add(
                            sum(self.assignment[sch_ver, week, area, doctor,
                                                day] for day in all_days
                                for doctor in all_doctors) == required_days)

        # Doctor can work at only one area at a time (per day)
        for doctor in all_doctors:
            for week in all_weeks:
                for day in all_days:
                    self.model.Add(
                        sum([
                            self.assignment[sv, week, a, doctor, day]
                            for sv in all_schedule_versions for a in all_areas
                        ]) <= 1)

        # Ensure that each day of the week is accounted for and no duplicate days
        for week in all_weeks:
            for day in all_days:
                for a in all_areas:
                    self.model.Add(
                        sum([
                            self.assignment[sv, week, a, d, day]
                            for sv in all_schedule_versions
                            for d in all_doctors
                        ]) == 1)

        # Maximum work days for each doctor
        for week in all_weeks:
            for doctor in all_doctors:
                self.model.Add(
                    sum([
                        self.assignment[sv, week, a, doctor, day]
                        for sv in all_schedule_versions for a in all_areas
                        for day in all_days
                    ]) <= self.problem.doctor_work_days[doctor])

        # Doctor makes all the classes of a area's course
        # So if Ian can teach math and history, he can only teach it in his course
        # If Donald also teaches history, students in his course would never be taught by Ian
        # doctor_schedule_versions = {}
        # for level in all_schedules:
        #   for section in all_versions:
        #     course = level * self.num_versions + section
        #     for area in all_areas:
        #       for t in all_doctors:
        #         name = 'C:{%i} S:{%i} T:{%i}' % (course, area, doctor)
        #         doctor_schedule_versions[course, area, t] = self.model.NewBoolVar(name)
        #         temp_array = [
        #             self.assignment[course, area, t, slot] for slot in all_slots
        #         ]
        #         self.model.AddMaxEquality(doctor_schedule_versions[course, area, t],
        #                                   temp_array)
        #       self.model.Add(
        #           sum(doctor_schedule_versions[course, area, t]
        #               for t in all_doctors) == 1)

        # Solution collector
        self.collector = None
Beispiel #2
0
def SolveRcpsp(problem, proto_file):
    # Determine problem type.
    problem_type = ('Resource investment'
                    if problem.is_resource_investment else 'RCPSP')

    if problem.is_rcpsp_max:
        problem_type += '/Max delay'
    if problem.is_consumer_producer:
        print('Solving %s with %i reservoir resources and %i tasks' %
              (problem_type, len(problem.resources), len(problem.tasks)))
    else:
        print('Solving %s with %i resources and %i tasks' %
              (problem_type, len(problem.resources), len(problem.tasks)))

    # Create the model.
    model = cp_model.CpModel()

    num_tasks = len(problem.tasks)
    num_resources = len(problem.resources)

    all_tasks = range(num_tasks)
    all_active_tasks = range(1, num_tasks - 1)
    all_resources = range(num_resources)

    horizon = problem.deadline if problem.deadline != -1 else problem.horizon
    if horizon == -1:  # Naive computation.
        horizon = sum(
            max(r.duration for r in t.recipes) for t in problem.tasks)
        if problem.is_rcpsp_max:
            for t in problem.tasks:
                for sd in t.successor_delays:
                    for rd in sd.recipe_delays:
                        for d in rd.min_delays:
                            horizon += abs(d)
    print('  - horizon = %i' % horizon)

    # Containers used to build resources.
    intervals_per_resource = defaultdict(list)
    demands_per_resource = defaultdict(list)
    presences_per_resource = defaultdict(list)
    starts_per_resource = defaultdict(list)

    # Starts and ends for master interval variables.
    task_starts = {}
    task_ends = {}

    # Containers for per-recipe per task variables.
    alternatives_per_task = defaultdict(list)
    presences_per_task = defaultdict(list)
    starts_per_task = defaultdict(list)
    ends_per_task = defaultdict(list)

    # Create tasks.
    for t in all_active_tasks:
        task = problem.tasks[t]

        if len(task.recipes) == 1:
            # Create interval.
            recipe = task.recipes[0]
            task_starts[t] = model.NewIntVar(0, horizon,
                                             'start_of_task_%i' % t)
            task_ends[t] = model.NewIntVar(0, horizon, 'end_of_task_%i' % t)
            interval = model.NewIntervalVar(task_starts[t], recipe.duration,
                                            task_ends[t], 'interval_%i' % t)

            # Store for later.
            alternatives_per_task[t].append(interval)
            starts_per_task[t].append(task_starts[t])
            ends_per_task[t].append(task_ends[t])
            presences_per_task[t].append(1)

            # Register for resources.
            for i in range(len(recipe.demands)):
                demand = recipe.demands[i]
                res = recipe.resources[i]
                demands_per_resource[res].append(demand)
                if problem.resources[res].renewable:
                    intervals_per_resource[res].append(interval)
                else:
                    starts_per_resource[res].append(task_starts[t])
                    presences_per_resource[res].append(1)
        else:
            all_recipes = range(len(task.recipes))

            # Compute duration range.
            min_size = min(recipe.duration for recipe in task.recipes)
            max_size = max(recipe.duration for recipe in task.recipes)

            # Create one optional interval per recipe.
            for r in all_recipes:
                recipe = task.recipes[r]
                is_present = model.NewBoolVar('is_present_%i_r%i' % (t, r))
                start = model.NewOptionalIntVar(0, horizon, is_present,
                                                'start_%i_r%i' % (t, r))
                end = model.NewOptionalIntVar(0, horizon, is_present,
                                              'end_%i_r%i' % (t, r))
                interval = model.NewOptionalIntervalVar(
                    start, recipe.duration, end, is_present,
                    'interval_%i_r%i' % (t, r))

                # Store variables.
                alternatives_per_task[t].append(interval)
                starts_per_task[t].append(start)
                ends_per_task[t].append(end)
                presences_per_task[t].append(is_present)

                # Register intervals in resources.
                for i in range(len(recipe.demands)):
                    demand = recipe.demands[i]
                    res = recipe.resources[i]
                    demands_per_resource[res].append(demand)
                    if problem.resources[res].renewable:
                        intervals_per_resource[res].append(interval)
                    else:
                        starts_per_resource[res].append(start)
                        presences_per_resource[res].append(is_present)

            # Create the master interval for the task.
            task_starts[t] = model.NewIntVar(0, horizon,
                                             'start_of_task_%i' % t)
            task_ends[t] = model.NewIntVar(0, horizon, 'end_of_task_%i' % t)
            duration = model.NewIntVar(min_size, max_size,
                                       'duration_of_task_%i' % t)
            interval = model.NewIntervalVar(task_starts[t], duration,
                                            task_ends[t], 'interval_%i' % t)

            # Link with optional per-recipe copies.
            for r in all_recipes:
                p = presences_per_task[t][r]
                model.Add(
                    task_starts[t] == starts_per_task[t][r]).OnlyEnforceIf(p)
                model.Add(task_ends[t] == ends_per_task[t][r]).OnlyEnforceIf(p)
                model.Add(
                    duration == task.recipes[r].duration).OnlyEnforceIf(p)
            model.Add(sum(presences_per_task[t]) == 1)

    # Create makespan variable
    makespan = model.NewIntVar(0, horizon, 'makespan')

    # Add precedences.
    if problem.is_rcpsp_max:
        for t in all_active_tasks:
            task = problem.tasks[t]
            num_modes = len(task.recipes)
            num_successors = len(task.successors)

            for s in range(num_successors):
                n = task.successors[s]
                delay_matrix = task.successor_delays[s]
                num_other_modes = len(problem.tasks[n].recipes)
                for m1 in range(num_modes):
                    s1 = starts_per_task[t][m1]
                    if n == num_tasks - 1:
                        delay = delay_matrix.recipe_delays[m1].min_delays[0]
                        model.Add(s1 + delay <= makespan)
                    else:
                        for m2 in range(num_other_modes):
                            delay = delay_matrix.recipe_delays[m1].min_delays[
                                m2]
                            s2 = starts_per_task[n][m2]
                            model.Add(s1 + delay <= s2)
    else:  # Normal dependencies (task ends before the start of successors).
        for t in all_active_tasks:
            for n in problem.tasks[t].successors:
                if n == num_tasks - 1:
                    model.Add(task_ends[t] <= makespan)
                else:
                    model.Add(task_ends[t] <= task_starts[n])

    # Containers for resource investment problems.
    capacities = []
    max_cost = 0

    # Create resources.
    for r in all_resources:
        resource = problem.resources[r]
        c = resource.max_capacity
        if c == -1:
            c = sum(demands_per_resource[r])

        if problem.is_resource_investment:
            capacity = model.NewIntVar(0, c, 'capacity_of_%i' % r)
            model.AddCumulative(intervals_per_resource[r],
                                demands_per_resource[r], capacity)
            capacities.append(capacity)
            max_cost += c * resource.unit_cost
        elif resource.renewable:
            if intervals_per_resource[r]:
                model.AddCumulative(intervals_per_resource[r],
                                    demands_per_resource[r], c)
        elif presences_per_resource[r]:  # Non empty non renewable resource.
            if problem.is_consumer_producer:
                model.AddReservoirConstraint(starts_per_resource[r],
                                             demands_per_resource[r],
                                             resource.min_capacity,
                                             resource.max_capacity)
            else:
                model.Add(
                    sum(presences_per_resource[r][i] *
                        demands_per_resource[r][i]
                        for i in range(len(presences_per_resource[r]))) <= c)

    # Objective.
    if problem.is_resource_investment:
        objective = model.NewIntVar(0, max_cost, 'capacity_costs')
        model.Add(objective == sum(problem.resources[i].unit_cost *
                                   capacities[i]
                                   for i in range(len(capacities))))
    else:
        objective = makespan

    model.Minimize(objective)

    if proto_file:
        print('Writing proto to %s' % proto_file)
        text_file = open(proto_file, 'w')
        text_file.write(str(model))
        text_file.close()

    # Solve model.
    solver = cp_model.CpSolver()
    solution_printer = SolutionPrinter()
    status = solver.SolveWithSolutionObserver(model, solution_printer)
    print('Solve status: %s' % solver.StatusName(status))
    print('Optimal objective value: %i' % solver.ObjectiveValue())
    print('Statistics')
    print('  - conflicts : %i' % solver.NumConflicts())
    print('  - branches  : %i' % solver.NumBranches())
    print('  - wall time : %f s' % solver.WallTime())
Beispiel #3
0
def LiteralSample():
    model = cp_model.CpModel()
    x = model.NewBoolVar('x')
    not_x = x.Not()
    print(x)
    print(not_x)
Beispiel #4
0
def jobshop_with_maintenance():
    """Solves a jobshop with maintenance on one machine."""
    # Create the model.
    model = cp_model.CpModel()

    jobs_data = [  # task = (machine_id, processing_time).
        [(0, 3), (1, 2), (2, 2)],  # Job0
        [(0, 2), (2, 1), (1, 4)],  # Job1
        [(1, 4), (2, 3)]  # Job2
    ]

    machines_count = 1 + max(task[0] for job in jobs_data for task in job)
    all_machines = range(machines_count)

    # Computes horizon dynamically as the sum of all durations.
    horizon = sum(task[1] for job in jobs_data for task in job)

    # Named tuple to store information about created variables.
    task_type = collections.namedtuple('Task', 'start end interval')
    # Named tuple to manipulate solution information.
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index duration')

    # Creates job intervals and add to the corresponding machine lists.
    all_tasks = {}
    machine_to_intervals = collections.defaultdict(list)

    for job_id, job in enumerate(jobs_data):
        for task_id, task in enumerate(job):
            machine = task[0]
            duration = task[1]
            suffix = '_%i_%i' % (job_id, task_id)
            start_var = model.NewIntVar(0, horizon, 'start' + suffix)
            end_var = model.NewIntVar(0, horizon, 'end' + suffix)
            interval_var = model.NewIntervalVar(start_var, duration, end_var,
                                                'interval' + suffix)
            all_tasks[job_id, task_id] = task_type(start=start_var,
                                                   end=end_var,
                                                   interval=interval_var)
            machine_to_intervals[machine].append(interval_var)

    # Add maintenance interval (machine 0 is not available on time {4, 5, 6, 7}).
    machine_to_intervals[0].append(model.NewIntervalVar(4, 4, 8, 'weekend_0'))

    # Create and add disjunctive constraints.
    for machine in all_machines:
        model.AddNoOverlap(machine_to_intervals[machine])

    # Precedences inside a job.
    for job_id, job in enumerate(jobs_data):
        for task_id in range(len(job) - 1):
            model.Add(all_tasks[job_id, task_id +
                                1].start >= all_tasks[job_id, task_id].end)

    # Makespan objective.
    obj_var = model.NewIntVar(0, horizon, 'makespan')
    model.AddMaxEquality(obj_var, [
        all_tasks[job_id, len(job) - 1].end
        for job_id, job in enumerate(jobs_data)
    ])
    model.Minimize(obj_var)

    # Solve model.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    # Output solution.
    if status == cp_model.OPTIMAL:
        # Create one list of assigned tasks per machine.
        assigned_jobs = collections.defaultdict(list)
        for job_id, job in enumerate(jobs_data):
            for task_id, task in enumerate(job):
                machine = task[0]
                assigned_jobs[machine].append(
                    assigned_task_type(start=solver.Value(
                        all_tasks[job_id, task_id].start),
                                       job=job_id,
                                       index=task_id,
                                       duration=task[1]))

        # Create per machine output lines.
        output = ''
        for machine in all_machines:
            # Sort by starting time.
            assigned_jobs[machine].sort()
            sol_line_tasks = 'Machine ' + str(machine) + ': '
            sol_line = '           '

            for assigned_task in assigned_jobs[machine]:
                name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)
                # Add spaces to output to align columns.
                sol_line_tasks += '%-10s' % name
                start = assigned_task.start
                duration = assigned_task.duration

                sol_tmp = '[%i,%i]' % (start, start + duration)
                # Add spaces to output to align columns.
                sol_line += '%-10s' % sol_tmp

            sol_line += '\n'
            sol_line_tasks += '\n'
            output += sol_line_tasks
            output += sol_line

        # Finally print the solution found.
        print('Optimal Schedule Length: %i' % solver.ObjectiveValue())
        print(output)
Beispiel #5
0
    def solve_correction_term(self):
        if len(self.a) == 0:
            raise Exception(
                'First array of community/group numbers is empty! Please set it as'
            )
        if len(self.b) == 0:
            raise Exception(
                'Second array of community/group numbers is empty! Please set it as'
            )
        if sum(self.a) is not sum(self.b):
            raise Exception(
                'The two arrays represent networks with different amount of nodes. Their sums is not equal.'
            )

        #Constant declaration
        self.inform('Problem constants:')
        n = sum(self.a)
        R = len(self.a)
        S = len(self.b)
        self.inform(f'n = {n}, R = {R}, S = {S}')
        for i in range(R):
            exec(f'a{i+1} = self.a[i]')
        for i in range(S):
            exec(f'b{i+1} = self.b[i]')

        model = cp_model.CpModel()

        #Variable declaration
        self.inform('Declaring variables:')
        for i in range(R):
            exp = ''
            for j in range(S):
                exec(f'c{i+1}{j+1} = model.NewIntVar(0, n, \'c{i+1}{j+1}\')')
                exp += f'c{i+1}{j+1}  '
            self.inform(exp)

        #Overlooping for code clarity
        self.inform('First set of constraints:')
        for i in range(R):
            exp = ''
            for j in range(S):
                exp += f'+ c{i+1}{j+1} ' if j > 0 else f'c{i+1}1 '
            exp += f'== a{i+1}'
            self.inform(exp)
            model.Add(eval(exp))

        #Overlooping for code clarity
        self.inform('Second set of constraints:')
        for j in range(S):
            exp = ''
            for i in range(R):
                exp += f'+ c{i+1}{j+1} ' if i > 0 else f'c1{j+1} '
            exp += f'== b{j+1}'
            self.inform(exp)
            model.Add(eval(exp))

        solver = cp_model.CpSolver()
        self.inform('Starting to solve...')
        status = solver.SearchForAllSolutions(model, self.solution_callback)

        self.inform('Found %i solutions' % self.solution_count())
        self.inform('All solutions found: ', status == cp_model.OPTIMAL)
        self.inform('-' * 50)

        return self.solution_count()
Beispiel #6
0
    def solve_with_discrete_model(num_tables, table_capacity,
                                  min_known_neighbors, C, names):
        num_guests = len(C)
        all_tables = range(num_tables)
        all_guests = range(num_guests)
        maxSolutions = 1

        # Create the cp model.
        model = cp_model.CpModel()

        #
        # Decision variables
        #
        seats = {}
        for t in all_tables:
            for g in all_guests:
                seats[(t, g)] = model.NewBoolVar("guest %i seats on table %i" %
                                                 (g, t))

        colocated = {}
        for g1 in range(num_guests - 1):
            for g2 in range(g1 + 1, num_guests):
                colocated[(g1, g2)] = model.NewBoolVar(
                    "guest %i seats with guest %i" % (g1, g2))

        same_table = {}
        for g1 in range(num_guests - 1):
            for g2 in range(g1 + 1, num_guests):
                for t in all_tables:
                    same_table[(g1, g2, t)] = model.NewBoolVar(
                        "guest %i seats with guest %i on table %i" %
                        (g1, g2, t))

        # Objective
        model.Maximize(
            sum(C[g1][g2] * colocated[g1, g2] for g1 in range(num_guests - 1)
                for g2 in range(g1 + 1, num_guests) if C[g1][g2] > 0))

        #
        # Constraints
        #

        # Everybody seats at one table.
        for g in all_guests:
            model.Add(sum(seats[(t, g)] for t in all_tables) == 1)

        # Tables have a max capacity.
        for t in all_tables:
            model.Add(sum(seats[(t, g)] for g in all_guests) <= table_capacity)

        # Link colocated with seats
        for g1 in range(num_guests - 1):
            for g2 in range(g1 + 1, num_guests):
                for t in all_tables:
                    # Link same_table and seats.
                    model.AddBoolOr([
                        seats[(t, g1)].Not(), seats[(t, g2)].Not(),
                        same_table[(g1, g2, t)]
                    ])
                    model.AddImplication(same_table[(g1, g2, t)],
                                         seats[(t, g1)])
                    model.AddImplication(same_table[(g1, g2, t)],
                                         seats[(t, g2)])

                # Link colocated and same_table.
                model.Add(
                    sum(same_table[(g1, g2, t)]
                        for t in all_tables) == colocated[(g1, g2)])

        # Min known neighbors rule.
        for t in all_tables:
            model.Add(
                sum(same_table[(g1, g2, t)] for g1 in range(num_guests - 1)
                    for g2 in range(g1 + 1, num_guests) for t in all_tables
                    if C[g1][g2] > 0) >= min_known_neighbors)

        # Symmetry breaking. First guest seats on the first table.
        model.Add(seats[(0, 0)] == 1)

        ### Solve model
        solver = cp_model.CpSolver()
        solution_printer = WeddingChartPrinter(seats, names, num_tables,
                                               num_guests, maxSolutions)
        solver.SolveWithSolutionCallback(model, solution_printer)
        return solution_printer.getSolution()
Beispiel #7
0
def scheduling(body):
    # data = {
    #     'cantJobs': "3",
    #     'cantTasks': "4",
    #     'tiempoTasks':  # lo que se demora cada tarea
    #            [3, 3, 2, 1],
    #     'precedencia':  # restricciones de precedencia, son del tipo endBeforeStart(tarea1, tarea2)
    #            [[4, 3],
    #            [3, 2],
    #            [2, 1]],
    #     'cantRecursos': "2",
    #     'cantUnidades': # cantidad de cada recurso
    #           [1, 2],
    #     'demandaTasks':
    #         [[1, 0],
    #          [1, 1],
    #          [0, 1],
    #          [1, 0]]
    # }

    json_data = body
    print("llego")
    print(json_data)
    cant_jobs = int(json_data['cantJobs'])
    cant_tasks = int(json_data['cantTasks'])
    tiempo_tasks = json_data['tiempoTasks']
    precedencia = (json_data['precedencia'])
    cant_recursos = int(json_data['cantRecursos'])
    cant_unidades = json_data['cantUnidades']
    demanda_tasks = json_data['demandaTasks']

    # crear modelo
    model = cp_model.CpModel()

    # crear las variables de decision: intervalos para cada task
    task_type = namedtuple('task_type',
                           'jobId taskId start end interval demand')
    jobs = []
    all_tasks = []
    limite = sum(
        tiempo_tasks) * cant_jobs  # limite de tiempo para las variables
    for j in range(cant_jobs):
        tasks = []
        for t in range(cant_tasks):
            id = '_' + str(j) + '_' + str(t)

            start = model.NewIntVar(0, limite, 'start' + id)
            duration = tiempo_tasks[t]
            end = model.NewIntVar(0, limite, 'end' + id)
            interval = model.NewIntervalVar(start, duration, end,
                                            'interval' + id)

            demand = demanda_tasks[t]

            task = task_type(j, t, start, end, interval, demand)
            tasks.append(task)
            all_tasks.append(task)
        jobs.append(tasks)

    print(jobs)

    # Restricciones
    # Precedencia
    for p in precedencia:
        end_task = p[0] - 1
        before_start_task = p[1] - 1
        for job in jobs:
            model.Add(job[end_task].end <= job[before_start_task].start)

    # Recursos: va a ser siempre con reposición, que el acumulado de la demanda de cada recurso no supere la capacidad
    # en un momento dado
    for r in range(cant_recursos):
        model.AddCumulative(
            [task.interval
             for task in all_tasks],  # los intervalos de los tasks
            [task.demand[r]
             for task in all_tasks],  # la demanda por cada task de ese recurso
            cant_unidades[r])  # la capacidad de cada recurso

    # Objetivo: crear un timeSpan que termine lo antes posible la ultima tarea del ultimo job
    obj_var = model.NewIntVar(0, limite, 'makespan')
    model.AddMaxEquality(obj_var, [task.end for task in job for job in jobs])
    model.Minimize(obj_var)

    # Resolver el modelo
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    if status == cp_model.OPTIMAL:
        solution = []
        for task in all_tasks:
            solution.append({
                'job': task.jobId + 1,
                'task': task.taskId + 1,
                'start': solver.Value(task.start),
                'end': solver.Value(task.end)
            })
        answer = {'error': False, 'solution': solution}

    else:
        answer = {'error': True, 'message': 'No existe una solución'}
    print(solution)
    print(answer)
    return answer
Beispiel #8
0
def main():
  # Creates the solver.
  model = cp_model.CpModel()

  machines_count = 6
  jobs_count = 6
  all_machines = range(0, machines_count)
  all_jobs = range(0, jobs_count)

  durations = [[1, 3, 6, 7, 3, 6], [8, 5, 10, 10, 10, 4], [5, 4, 8, 9, 1, 7],
               [5, 5, 5, 3, 8, 9], [9, 3, 5, 4, 3, 1], [3, 3, 9, 10, 4, 1]]

  machines = [[2, 0, 1, 3, 5, 4], [1, 2, 4, 5, 0, 3], [2, 3, 5, 0, 1, 4],
              [1, 0, 2, 3, 4, 5], [2, 1, 4, 5, 0, 3], [1, 3, 5, 0, 4, 2]]

  # Computes horizon dynamically.
  horizon = sum([sum(durations[i]) for i in all_jobs])

  Task = collections.namedtuple('Task', 'start end interval')

  # Creates jobs.
  all_tasks = {}
  for i in all_jobs:
    for j in all_machines:
      start_var = model.NewIntVar(0, horizon, 'start_%i_%i' % (i, j))
      duration = durations[i][j]
      end_var = model.NewIntVar(0, horizon, 'end_%i_%i' % (i, j))
      interval_var = model.NewIntervalVar(start_var, duration, end_var,
                                          'interval_%i_%i' % (i, j))
      all_tasks[(i, j)] = Task(
          start=start_var, end=end_var, interval=interval_var)

  # Create disjuctive constraints.
  machine_to_jobs = {}
  for i in all_machines:
    machines_jobs = []
    for j in all_jobs:
      for k in all_machines:
        if machines[j][k] == i:
          machines_jobs.append(all_tasks[(j, k)].interval)
    machine_to_jobs[i] = machines_jobs
    model.AddNoOverlap(machines_jobs)

  # Precedences inside a job.
  for i in all_jobs:
    for j in range(0, machines_count - 1):
      model.Add(all_tasks[(i, j + 1)].start >= all_tasks[(i, j)].end)

  # Makespan objective.
  obj_var = model.NewIntVar(0, horizon, 'makespan')
  model.AddMaxEquality(
      obj_var, [all_tasks[(i, machines_count - 1)].end for i in all_jobs])
  model.Minimize(obj_var)

  # Solve model.
  solver = cp_model.CpSolver()
  response = solver.Solve(model)

  # Output solution.
  if visualization.RunFromIPython():
    starts = [[solver.Value(all_tasks[(i, j)][0])
               for j in all_machines]
              for i in all_jobs]
    visualization.DisplayJobshop(starts, durations, machines, 'FT06')
  else:
    print('Optimal makespan: %i' % solver.ObjectiveValue())
Beispiel #9
0
def steel_mill_slab(problem, break_symmetries, output_proto):
    """Solves the Steel Mill Slab Problem."""
    ### Load problem.
    (num_slabs, capacities, num_colors, orders) = build_problem(problem)

    num_orders = len(orders)
    num_capacities = len(capacities)
    all_slabs = range(num_slabs)
    all_colors = range(num_colors)
    all_orders = range(len(orders))
    print('Solving steel mill with %i orders, %i slabs, and %i capacities' %
          (num_orders, num_slabs, num_capacities - 1))

    # Compute auxilliary data.
    widths = [x[0] for x in orders]
    colors = [x[1] for x in orders]
    max_capacity = max(capacities)
    loss_array = [
        min(x for x in capacities if x >= c) - c
        for c in range(max_capacity + 1)
    ]
    max_loss = max(loss_array)
    orders_per_color = [[o for o in all_orders if colors[o] == c + 1]
                        for c in all_colors]
    unique_color_orders = [
        o for o in all_orders if len(orders_per_color[colors[o] - 1]) == 1
    ]

    ### Model problem.

    # Create the model and the decision variables.
    model = cp_model.CpModel()
    assign = [[
        model.NewBoolVar('assign_%i_to_slab_%i' % (o, s)) for s in all_slabs
    ] for o in all_orders]
    loads = [
        model.NewIntVar(0, max_capacity, 'load_of_slab_%i' % s)
        for s in all_slabs
    ]
    color_is_in_slab = [[
        model.NewBoolVar('color_%i_in_slab_%i' % (c + 1, s))
        for c in all_colors
    ] for s in all_slabs]

    # Compute load of all slabs.
    for s in all_slabs:
        model.Add(
            sum(assign[o][s] * widths[o] for o in all_orders) == loads[s])

    # Orders are assigned to one slab.
    for o in all_orders:
        model.Add(sum(assign[o]) == 1)

    # Redundant constraint (sum of loads == sum of widths).
    model.Add(sum(loads) == sum(widths))

    # Link present_colors and assign.
    for c in all_colors:
        for s in all_slabs:
            for o in orders_per_color[c]:
                model.AddImplication(assign[o][s], color_is_in_slab[s][c])
                model.AddImplication(color_is_in_slab[s][c].Not(),
                                     assign[o][s].Not())

    # At most two colors per slab.
    for s in all_slabs:
        model.Add(sum(color_is_in_slab[s]) <= 2)

    # Project previous constraint on unique_color_orders
    for s in all_slabs:
        model.Add(sum(assign[o][s] for o in unique_color_orders) <= 2)

    # Symmetry breaking.
    for s in range(num_slabs - 1):
        model.Add(loads[s] >= loads[s + 1])

    # Collect equivalent orders.
    width_to_unique_color_order = {}
    ordered_equivalent_orders = []
    for c in all_colors:
        colored_orders = orders_per_color[c]
        if not colored_orders:
            continue
        if len(colored_orders) == 1:
            o = colored_orders[0]
            w = widths[o]
            if w not in width_to_unique_color_order:
                width_to_unique_color_order[w] = [o]
            else:
                width_to_unique_color_order[w].append(o)
        else:
            local_width_to_order = {}
            for o in colored_orders:
                w = widths[o]
                if w not in local_width_to_order:
                    local_width_to_order[w] = []
                local_width_to_order[w].append(o)
            for w, os in local_width_to_order.items():
                if len(os) > 1:
                    for p in range(len(os) - 1):
                        ordered_equivalent_orders.append((os[p], os[p + 1]))
    for w, os in width_to_unique_color_order.items():
        if len(os) > 1:
            for p in range(len(os) - 1):
                ordered_equivalent_orders.append((os[p], os[p + 1]))

    # Create position variables if there are symmetries to be broken.
    if break_symmetries and ordered_equivalent_orders:
        print('  - creating %i symmetry breaking constraints' %
              len(ordered_equivalent_orders))
        positions = {}
        for p in ordered_equivalent_orders:
            if p[0] not in positions:
                positions[p[0]] = model.NewIntVar(0, num_slabs - 1,
                                                  'position_of_slab_%i' % p[0])
                model.AddMapDomain(positions[p[0]], assign[p[0]])
            if p[1] not in positions:
                positions[p[1]] = model.NewIntVar(0, num_slabs - 1,
                                                  'position_of_slab_%i' % p[1])
                model.AddMapDomain(positions[p[1]], assign[p[1]])
            # Finally add the symmetry breaking constraint.
            model.Add(positions[p[0]] <= positions[p[1]])

    # Objective.
    obj = model.NewIntVar(0, num_slabs * max_loss, 'obj')
    losses = [model.NewIntVar(0, max_loss, 'loss_%i' % s) for s in all_slabs]
    for s in all_slabs:
        model.AddElement(loads[s], loss_array, losses[s])
    model.Add(obj == sum(losses))
    model.Minimize(obj)

    ### Solve model.
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = 8
    objective_printer = cp_model.ObjectiveSolutionPrinter()
    status = solver.SolveWithSolutionCallback(model, objective_printer)

    ### Output the solution.
    if status in (cp_model.OPTIMAL, cp_model.FEASIBLE):
        print('Loss = %i, time = %f s, %i conflicts' %
              (solver.ObjectiveValue(), solver.WallTime(),
               solver.NumConflicts()))
    else:
        print('No solution')
def MinimalJobshopSat():
    """Minimal jobshop problem."""
    # Create the model.
    model = cp_model.CpModel()
def MinimalJobshopToy():
    #define the model
    model = cp_model.CpModel()
    '''Import Data'''
    #set data directory
    data_dir = 'Toy Job Shop problem.xlsx'

    imported_data_df = pd.read_excel(data_dir, sheet_name='Data')

    #print (imported_data_df)

    #check column format
    imported_data_df.dtypes

    #Organisation                      object
    #Task 1 completion date    datetime64[ns]
    #Task 2 Completion date    datetime64[ns]
    #Task 3 length                      int64
    #Task 4 length                      int64
    #dtype: object

    #Create initialisation date 2019-10-01
    imported_data_df = imported_data_df.assign(
        Initialisation_Date=pd.to_datetime('2019-10-01'))

    #create Task_1_length column (int)
    imported_data_df = imported_data_df.assign(
        Task_1_length=((imported_data_df['Task 1 completion date'] -
                        imported_data_df['Initialisation_Date']) /
                       np.timedelta64(1, 'D')).astype(int))

    #creating Task_2_lenght on the assumption that task two can start only after task 1 is completed. is that the case?
    imported_data_df = imported_data_df.assign(
        Task_2_length=((imported_data_df['Task 2 Completion date'] -
                        imported_data_df['Task 1 completion date']) /
                       np.timedelta64(1, 'D')).astype(int))
    #df['diff_days'] = df['End_date'] - df['Start_date']
    #df['diff_days']=df['diff_days']/np.timedelta64(1,'D')

    #find max(Task 2 Completion date) and define Transition_Date_Start as max(Task 2 Completion date) +5
    imported_data_df = imported_data_df.assign(Max_Preparation_Task_2_dt=max(
        imported_data_df['Task 2 Completion date']))
    #imported_data_df=imported_data_df.assign(Transition_Date_Start =  imported_data_df['Max_Preparation_Task_2_dt'] + 5 )
    imported_data_df["Transition_Date_Start"] = imported_data_df[
        "Max_Preparation_Task_2_dt"] + timedelta(days=5)

    #compute waiting days between task2 end date and transition start date
    wait_days = imported_data_df['Transition_Date_Start'] - imported_data_df[
        'Task 2 Completion date']
    #convert the days into integer format
    Pause_length = []
    for i in wait_days:
        j = i.days
        Pause_length.append(j)
    #Add this column to the dataframe
    imported_data_df['Pause_length'] = Pause_length
    '''Define the data'''
    df = imported_data_df[[
        'Organisation', 'Task_1_length', 'Task_2_length', 'Pause_length',
        'Task 3 length', 'Task 4 length'
    ]]

    jobs_data = []
    for j in range(1, len(df.columns)):
        ls = []
        for i in range(0, len(df.index)):
            task = (i + 1, df.iloc[i, j])
            ls.append(task)
        jobs_data.append(ls)

    org_count = 1 + max(task[0] for job in jobs_data for task in job)
    all_organisations = range(org_count)
    '''Define Variables'''
    # Named tuple to store information about created variables.
    task_type = collections.namedtuple('task_type', 'start end interval')
    # Named tuple to manipulate solution information.
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index duration')

    # Create job intervals and add to the corresponding machine lists.
    all_tasks = {}
    org_to_intervals = collections.defaultdict(list)

    # Computes horizon dynamically as the sum of all durations.
    horizon = sum(task[1] for job in jobs_data for task in job)

    for job_id, job in enumerate(jobs_data):
        for task_id, task in enumerate(job):
            organisation = task[0]
            duration = task[1]
            suffix = '_%i_%i' % (job_id, task_id)
            start_var = model.NewIntVar(0, int(horizon), 'start' + suffix)
            end_var = model.NewIntVar(0, int(horizon), 'end' + suffix)
            interval_var = model.NewIntervalVar(start_var, duration, end_var,
                                                'interval' + suffix)
            all_tasks[job_id, task_id] = task_type(start=start_var,
                                                   end=end_var,
                                                   interval=interval_var)
            org_to_intervals[organisation].append(interval_var)
    '''Define Constraints'''
    # Create and add disjunctive constraints.
    for organisation in all_organisations:
        model.AddNoOverlap(org_to_intervals[organisation])
    '''Define the Objective'''
    # Makespan objective.
    obj_var = model.NewIntVar(0, int(horizon), 'makespan')
    model.AddMaxEquality(obj_var, [
        all_tasks[job_id, len(job) - 1].end
        for job_id, job in enumerate(jobs_data)
    ])
    model.Minimize(obj_var)
    '''Declare the Solver'''
    # Solve model.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    '''Display the results'''
    # Create one list of assigned tasks per machine.
    assigned_jobs = collections.defaultdict(list)
    for job_id, job in enumerate(jobs_data):
        for task_id, task in enumerate(job):
            organisation = task[0]
            assigned_jobs[organisation].append(
                assigned_task_type(start=solver.Value(
                    all_tasks[job_id, task_id].start),
                                   job=job_id,
                                   index=task_id,
                                   duration=task[1]))

    # Create per organisation output lines.
    output = ''
    for organisation in all_organisations:
        # Sort by starting time.
        assigned_jobs[organisation].sort()
        sol_line_tasks = 'Organisation ' + str(organisation) + ': '
        sol_line = '           '

        for assigned_task in assigned_jobs[organisation]:
            name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)
            # Add spaces to output to align columns.
            sol_line_tasks += '%-10s' % name

            start = assigned_task.start
            duration = assigned_task.duration
            sol_tmp = '[%i,%i]' % (start, start + duration)
            # Add spaces to output to align columns.
            sol_line += '%-10s' % sol_tmp

        sol_line += '\n'
        sol_line_tasks += '\n'
        output += sol_line_tasks
        output += sol_line

    # Finally print the solution found.
    print('Optimal Schedule Length: %i' % solver.ObjectiveValue())
    print(output)
Beispiel #12
0
def model_powereco_plant():
    t = 'model_powereco_plant'  ### onde usar isto ....????
    ## creating a model
    the_model = cp_model.CpModel()

    # DATA ---
    C1 = 35 ### Capacity of a supplier ... 1 up to 3
    C2 = 50
    C3 = 40
    suppliers = 3 ### index 0 up to 2
    cities = 4   ### 0 .. 3 
    '''
    custo =  
    8*x11 +  6*x12 + 10*x13 + 9*x14 +
    9*x21 +  12*x22 + 13*x23 + 7*x24+
    14*x31 + 9*x32 + 16*x33 + 5*x34;
    '''
    ## transmission cost between suppliers (i -- rows) and cities (j--cols)
    cost = [ 
            [8,  6,  10, 9],
            [9,  12, 13, 7],
            [14, 9,  16, 5]
           ]

    ### Should be come from a file
    NINE_NINE = 999999 ### a constant
    #### VARIABLES
    ## ANOTHER IDEA AROUND THIS --- how much is going from i to j?
    ### Example x=[[s.NumVar(0,C[i][j],'')for j in range(n)]for i in range(n)
    x = [
         [the_model.NewIntVar(0, C1, 'x[0][%i]' % INDEX_1) for INDEX_1 in range(cities)] ,
         [the_model.NewIntVar(0, C2, 'x[1][%i]' % INDEX_2) for INDEX_2 in range(cities)] ,
         [the_model.NewIntVar(0, C3, 'x[2][%i]' % INDEX_3) for INDEX_3 in range(cities)] 
        ]
    ### range(start, range ) --- start in specific index   
    # 
    f_objective = the_model.NewIntVar (0, NINE_NINE, 'cost function')
    
    # CONSTRAINTS ADDED 
    ####x11 + x12 + x13 + x14 <= C1; %(Plant 1 supply constraint)
    ## C capacity of each Suppliers
    the_model.Add(sum(x[0][j] for j in range(cities)) <= C1)         
    the_model.Add(sum(x[1][j] for j in range(cities)) <= C2)
    the_model.Add(sum(x[2][j] for j in range(cities)) <= C3)

    '''
      x11 + x21 + x31 >= 45    /\
      x12 + x22 + x32 >= 20    /\
      x13 + x23 + x33 >= 30    /\ 
      x14 + x24 + x34 >= 30     ;
      >>> for i in range(1,4):    print(i)  ## learning Python
        ... 
        1
        2
        3
    '''
    ### Demand of each City 1..4 .... from these suppliers
    the_model.Add(sum(x[i][0] for i in range(suppliers)) >= 45)  
    the_model.Add(sum(x[i][1] for i in range(suppliers)) >= 20)  
    the_model.Add(sum(x[i][2] for i in range(suppliers)) >= 30)
    the_model.Add(sum(x[i][3] for i in range(suppliers)) >= 30)

    ### Objective Function
    the_model.Add(
        f_objective == sum(
            (cost[i][j] * x[i][j]) \
            for i in range(suppliers) \
            for j in  range(cities)
            )### of sum 
        )## of Add
    

    ### optmization  function or objective function 
    # OR:  the_model.Maximize(-less_DIF) 
    the_model.Minimize(f_objective)

    ### data_from_model = call the solver for model s
    # code calls the solver
    solver_OUT = cp_model.CpSolver()
    solver_OUT.parameters.max_time_in_seconds = 10
    status = solver_OUT.Solve(the_model)

    if status not in (cp_model.OPTIMAL, cp_model.FEASIBLE):
        raise ValueError("No solution was found for the given input values")
    else :
        my_print_VARS( x , suppliers, cities,  f_objective, solver_OUT )
        print("\n END SOLVER and Model ")
        print_t(40)

    return ###### end function
Beispiel #13
0
 def __init__(self, N, A):
     self.N = N
     self.A = A
     self.model = cp_model.CpModel()
def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file):
    """Solve the cutting stock with arc-flow and the CP-SAT solver."""
    items = regroup_and_count(DESIRED_LENGTHS)
    print('Items:', items)
    num_items = len(DESIRED_LENGTHS)

    max_capacity = max(POSSIBLE_CAPACITIES)
    states, transitions = create_state_graph(items, max_capacity)

    print('Dynamic programming has generated', len(states), 'states and',
          len(transitions), 'transitions')

    incoming_vars = collections.defaultdict(list)
    outgoing_vars = collections.defaultdict(list)
    incoming_sink_vars = []
    item_vars = collections.defaultdict(list)
    item_coeffs = collections.defaultdict(list)
    transition_vars = []

    model = cp_model.CpModel()

    objective_vars = []
    objective_coeffs = []

    for outgoing, incoming, item_index, card in transitions:
        count = items[item_index][1]
        max_count = count // card
        count_var = model.NewIntVar(
            0, max_count,
            'i%i_f%i_t%i_C%s' % (item_index, incoming, outgoing, card))
        incoming_vars[incoming].append(count_var)
        outgoing_vars[outgoing].append(count_var)
        item_vars[item_index].append(count_var)
        item_coeffs[item_index].append(card)
        transition_vars.append(count_var)

    for state_index, state in enumerate(states):
        if state_index == 0:
            continue
        exit_var = model.NewIntVar(0, num_items, 'e%i' % state_index)
        outgoing_vars[state_index].append(exit_var)
        incoming_sink_vars.append(exit_var)
        price = price_usage(state, POSSIBLE_CAPACITIES)
        objective_vars.append(exit_var)
        objective_coeffs.append(price)

    # Flow conservation
    for state_index in range(1, len(states)):
        model.Add(
            sum(incoming_vars[state_index]) == sum(outgoing_vars[state_index]))

    # Flow going out of the source must go in the sink
    model.Add(sum(outgoing_vars[0]) == sum(incoming_sink_vars))

    # Items must be placed
    for item_index, size_and_count in enumerate(items):
        num_arcs = len(item_vars[item_index])
        model.Add(
            sum(item_vars[item_index][i] * item_coeffs[item_index][i]
                for i in range(num_arcs)) == size_and_count[1])

    # Objective is the sum of waste
    model.Minimize(
        sum(objective_vars[i] * objective_coeffs[i]
            for i in range(len(objective_vars))))

    # Output model proto to file.
    if output_proto_file:
        output_file = open(output_proto_file, 'w')
        output_file.write(str(model.Proto()))
        output_file.close()

    # Solve model.
    solver = cp_model.CpSolver()
    solver.parameters.log_search_progress = True
    solver.parameters.num_search_workers = 8
    status = solver.Solve(model)
    print(solver.ResponseStats())
Beispiel #15
0
def SimpleSatProgram():
    """Minimal CP-SAT example to showcase calling the solver."""
    # Creates the model.
    model = cp_model.CpModel()

    # Creates the variables.
    num_vals = 4
    A1 = model.NewIntVar(1, num_vals, 'a1')
    A2 = model.NewIntVar(1, num_vals, 'a2')
    A3 = model.NewIntVar(1, num_vals, 'a3')
    A4 = model.NewIntVar(1, num_vals, 'a4')
    B1 = model.NewIntVar(1, num_vals, 'b1')
    B2 = model.NewIntVar(1, num_vals, 'b2')
    B3 = model.NewIntVar(1, num_vals, 'b3')
    B4 = model.NewIntVar(1, num_vals, 'b4')
    C1 = model.NewIntVar(1, num_vals, 'c1')
    C2 = model.NewIntVar(1, num_vals, 'c2')
    C3 = model.NewIntVar(1, num_vals, 'c3')
    C4 = model.NewIntVar(1, num_vals, 'c4')
    D1 = model.NewIntVar(1, num_vals, 'd1')
    D2 = model.NewIntVar(1, num_vals, 'd2')
    D3 = model.NewIntVar(1, num_vals, 'd3')
    D4 = model.NewIntVar(1, num_vals, 'd4')

    # Creates the constraints.

    model.Add(A1 != A2)
    model.Add(A1 != A3)
    model.Add(A1 != A4)
    model.Add(A1 != B1)
    model.Add(A1 != C1)
    model.Add(A1 != D1)
    model.Add(A2 != A3)
    model.Add(A2 != A4)
    model.Add(A2 != B2)
    model.Add(A2 != C2)
    model.Add(A2 != D2)
    model.Add(A3 != A4)
    model.Add(A3 != B3)
    model.Add(A3 != C3)
    model.Add(A3 != D3)
    model.Add(A4 != B4)
    model.Add(A4 != C4)
    model.Add(A4 != D4)
    model.Add(B1 != B2)
    model.Add(B1 != B3)
    model.Add(B1 != B4)
    model.Add(B1 != C1)
    model.Add(B1 != D1)
    model.Add(B2 != B3)
    model.Add(B2 != B4)
    model.Add(B2 != C2)
    model.Add(B2 != D2)
    model.Add(B3 != B4)
    model.Add(B3 != C3)
    model.Add(B3 != D3)
    model.Add(B4 != C4)
    model.Add(B4 != D4)
    model.Add(C1 != C2)
    model.Add(C1 != C3)
    model.Add(C1 != C4)
    model.Add(C1 != D1)
    model.Add(C2 != C3)
    model.Add(C2 != C4)
    model.Add(C2 != D2)
    model.Add(C3 != C4)
    model.Add(C3 != D3)
    model.Add(C4 != D4)
    model.Add(D1 != D2)
    model.Add(D1 != D3)
    model.Add(D1 != D4)

    if line1[1].isdigit():
        if line1[0] == "A1":
            model.Add(A1 == int(line1[1]))

        if line1[0] == "A2":
            model.Add(A2 == int(line1[1]))

        if line1[0] == "A3":
            model.Add(A3 == int(line1[1]))

        if line1[0] == "A4":
            model.Add(A4 == int(line1[1]))

        if line1[0] == "B1":
            model.Add(B1 == int(line1[1]))

        if line1[0] == "B2":
            model.Add(B2 == int(line1[1]))

        if line1[0] == "B3":
            model.Add(B3 == int(line1[1]))

        if line1[0] == "B4":
            model.Add(B4 == int(line1[1]))

        if line1[0] == "C1":
            model.Add(C1 == int(line1[1]))

        if line1[0] == "C2":
            model.Add(C2 == int(line1[1]))

        if line1[0] == "C3":
            model.Add(C3 == int(line1[1]))

        if line1[0] == "C4":
            model.Add(C4 == int(line1[1]))

        if line1[0] == "D1":
            model.Add(D1 == int(line1[1]))

        if line1[0] == "D2":
            model.Add(D2 == int(line1[1]))

        if line1[0] == "D3":
            model.Add(D3 == int(line1[1]))

        if line1[0] == "D4":
            model.Add(D4 == int(line1[1]))

    else:
        if line1[0] == "A1":
            if line1[1] == "A2":
                model.Add(A1 > A2)

            if line1[1] == "B1":
                model.Add(A1 > B1)

        if line1[0] == "A2":
            if line1[1] == "A1":
                model.Add(A2 > A1)

            if line1[1] == "A3":
                model.Add(A2 > A3)

            if line1[1] == "B2":
                model.Add(A2 > B2)

        if line1[0] == "A3":
            if line1[1] == "A2":
                model.Add(A3 > A2)

            if line1[1] == "A4":
                model.Add(A3 > A4)

            if line1[1] == "B3":
                model.Add(A3 > B3)

        if line1[0] == "A4":

            if line1[1] == "B4":
                model.Add(A4 > B4)
            if line1[1] == "A3":
                model.Add(A4 > A3)

        if line1[0] == "B1":
            if line1[1] == "A1":
                model.Add(B1 > A1)

            if line1[1] == "C1":
                model.Add(B1 > C1)

            if line1[1] == "B2":
                model.Add(B1 > B2)

        if line1[0] == "B2":
            if line1[1] == "A2":
                model.Add(B2 > A2)

            if line1[1] == "B1":
                model.Add(B2 > B1)

            if line1[1] == "B3":
                model.Add(B2 > B3)

            if line1[1] == "C2":
                model.Add(B2 > C2)

        if line1[0] == "B3":
            if line1[1] == "A3":
                model.Add(B3 > A3)

            if line1[1] == "B2":
                model.Add(B3 > B2)

            if line1[1] == "B4":
                model.Add(B3 > B4)

            if line1[1] == "C3":
                model.Add(B3 > C3)

        if line1[0] == "B4":
            if line1[1] == "A4":
                model.Add(B4 > A4)

            if line1[1] == "B3":
                model.Add(B4 > B3)

            if line1[1] == "C4":
                model.Add(B4 > C4)

        if line1[0] == "C1":
            if line1[1] == "B1":
                model.Add(C1 > B1)

            if line1[1] == "C2":
                model.Add(C1 > C2)

            if line1[1] == "D1":
                model.Add(C1 > D1)

        if line1[0] == "C2":
            if line1[1] == "B2":
                model.Add(C2 > B2)

            if line1[1] == "C1":
                model.Add(C2 > C1)

            if line1[1] == "C3":
                model.Add(C2 > C3)

            if line1[1] == "D2":
                model.Add(C2 > D2)

        if line1[0] == "C3":
            if line1[1] == "B3":
                model.Add(C3 > B3)

            if line1[1] == "C2":
                model.Add(C3 > C2)

            if line1[1] == "C4":
                model.Add(C3 > C4)

            if line1[1] == "D3":
                model.Add(C3 > D3)

        if line1[0] == "C4":

            if line1[1] == "B4":
                model.Add(C4 > B4)

            if line1[1] == "D2":
                model.Add(C4 > D4)

            if line1[1] == "C3":
                model.Add(C4 > C3)

        if line1[0] == "D1":

            if line1[1] == "C1":
                model.Add(D1 > C1)

            if line1[1] == "D2":
                model.Add(D1 > D2)

        if line1[0] == "D2":
            if line1[1] == "D1":
                model.Add(D2 > D1)

            if line1[1] == "C2":
                model.Add(D2 > C2)

            if line1[1] == "D3":
                model.Add(D2 > D3)

        if line1[0] == "D3":
            if line1[1] == "C3":
                model.Add(D3 > C3)

            if line1[1] == "D2":
                model.Add(D3 > D2)

            if line1[1] == "D4":
                model.Add(D3 > D4)
        if line1[0] == "D4":
            if line1[1] == "D3":
                model.Add(D4 > D3)

            if line1[1] == "C4":
                model.Add(D4 > C4)

#line

    if line2[1].isdigit():
        if line2[0] == "A1":
            model.Add(A1 == int(line2[1]))

        if line2[0] == "A2":
            model.Add(A2 == int(line2[1]))

        if line2[0] == "A3":
            model.Add(A3 == int(line2[1]))

        if line2[0] == "A4":
            model.Add(A4 == int(line2[1]))

        if line2[0] == "B1":
            model.Add(B1 == int(line2[1]))

        if line2[0] == "B2":
            model.Add(B2 == int(line2[1]))

        if line2[0] == "B3":
            model.Add(B3 == int(line2[1]))

        if line2[0] == "B4":
            model.Add(B4 == int(line2[1]))

        if line2[0] == "C1":
            model.Add(C1 == int(line2[1]))

        if line2[0] == "C2":
            model.Add(C2 == int(line2[1]))

        if line2[0] == "C3":
            model.Add(C3 == int(line2[1]))

        if line2[0] == "C4":
            model.Add(C4 == int(line2[1]))

        if line2[0] == "D1":
            model.Add(D1 == int(line2[1]))

        if line2[0] == "D2":
            model.Add(D2 == int(line2[1]))

        if line2[0] == "D3":
            model.Add(D3 == int(line2[1]))

        if line2[0] == "D4":
            model.Add(D4 == int(line2[1]))

    else:
        if line2[0] == "A1":
            if line2[1] == "A2":
                model.Add(A1 > A2)

            if line2[1] == "B1":
                model.Add(A1 > B1)

        if line2[0] == "A2":
            if line2[1] == "A1":
                model.Add(A2 > A1)

            if line2[1] == "A3":
                model.Add(A2 > A3)

            if line2[1] == "B2":
                model.Add(A2 > B2)

        if line2[0] == "A3":
            if line2[1] == "A2":
                model.Add(A3 > A2)

            if line2[1] == "A4":
                model.Add(A3 > A4)

            if line2[1] == "B3":
                model.Add(A3 > B3)

        if line2[0] == "A4":

            if line2[1] == "B4":
                model.Add(A4 > B4)
            if line2[1] == "A3":
                model.Add(A4 > A3)

        if line2[0] == "B1":
            if line2[1] == "A1":
                model.Add(B1 > A1)

            if line2[1] == "C1":
                model.Add(B1 > C1)

            if line2[1] == "B2":
                model.Add(B1 > B2)

        if line2[0] == "B2":
            if line2[1] == "A2":
                model.Add(B2 > A2)

            if line2[1] == "B1":
                model.Add(B2 > B1)

            if line2[1] == "B3":
                model.Add(B2 > B3)

            if line2[1] == "C2":
                model.Add(B2 > C2)

        if line2[0] == "B3":
            if line2[1] == "A3":
                model.Add(B3 > A3)

            if line2[1] == "B2":
                model.Add(B3 > B2)

            if line2[1] == "B4":
                model.Add(B3 > B4)

            if line2[1] == "C3":
                model.Add(B3 > C3)

        if line2[0] == "B4":
            if line2[1] == "A4":
                model.Add(B4 > A4)

            if line2[1] == "B3":
                model.Add(B4 > B3)

            if line2[1] == "C4":
                model.Add(B4 > C4)

        if line2[0] == "C1":
            if line2[1] == "B1":
                model.Add(C1 > B1)

            if line2[1] == "C2":
                model.Add(C1 > C2)

            if line2[1] == "D1":
                model.Add(C1 > D1)

        if line2[0] == "C2":
            if line2[1] == "B2":
                model.Add(C2 > B2)

            if line2[1] == "C1":
                model.Add(C2 > C1)

            if line2[1] == "C3":
                model.Add(C2 > C3)

            if line2[1] == "D2":
                model.Add(C2 > D2)

        if line2[0] == "C3":
            if line2[1] == "B3":
                model.Add(C3 > B3)

            if line2[1] == "C2":
                model.Add(C3 > C2)

            if line2[1] == "C4":
                model.Add(C3 > C4)

            if line2[1] == "D3":
                model.Add(C3 > D3)

        if line2[0] == "C4":

            if line2[1] == "B4":
                model.Add(C4 > B4)

            if line2[1] == "D2":
                model.Add(C4 > D4)

            if line2[1] == "C3":
                model.Add(C4 > C3)

        if line2[0] == "D1":

            if line2[1] == "C1":
                model.Add(D1 > C1)

            if line2[1] == "D2":
                model.Add(D1 > D2)

        if line2[0] == "D2":
            if line2[1] == "D1":
                model.Add(D2 > D1)

            if line2[1] == "C2":
                model.Add(D2 > C2)

            if line2[1] == "D3":
                model.Add(D2 > D3)

        if line2[0] == "D3":
            if line2[1] == "C3":
                model.Add(D3 > C3)

            if line2[1] == "D2":
                model.Add(D3 > D2)

            if line2[1] == "D4":
                model.Add(D3 > D4)
        if line2[0] == "D4":
            if line2[1] == "D3":
                model.Add(D4 > D3)

            if line2[1] == "C4":
                model.Add(D4 > C4)

#line3

    if line3[1].isdigit():
        if line3[0] == "A1":
            model.Add(A1 == int(line3[1]))

        if line3[0] == "A2":
            model.Add(A2 == int(line3[1]))

        if line3[0] == "A3":
            model.Add(A3 == int(line3[1]))

        if line3[0] == "A4":
            model.Add(A4 == int(line3[1]))

        if line3[0] == "B1":
            model.Add(B1 == int(line3[1]))

        if line3[0] == "B2":
            model.Add(B2 == int(line3[1]))

        if line3[0] == "B3":
            model.Add(B3 == int(line3[1]))

        if line3[0] == "B4":
            model.Add(B4 == int(line3[1]))

        if line3[0] == "C1":
            model.Add(C1 == int(line3[1]))

        if line3[0] == "C2":
            model.Add(C2 == int(line3[1]))

        if line3[0] == "C3":
            model.Add(C3 == int(line3[1]))

        if line3[0] == "C4":
            model.Add(C4 == int(line3[1]))

        if line3[0] == "D1":
            model.Add(D1 == int(line3[1]))

        if line3[0] == "D2":
            model.Add(D2 == int(line3[1]))

        if line3[0] == "D3":
            model.Add(D3 == int(line3[1]))

        if line3[0] == "D4":
            model.Add(D4 == int(line3[1]))

    else:
        if line3[0] == "A1":
            if line3[1] == "A2":
                model.Add(A1 > A2)

            if line3[1] == "B1":
                model.Add(A1 > B1)

        if line3[0] == "A2":
            if line3[1] == "A1":
                model.Add(A2 > A1)

            if line3[1] == "A3":
                model.Add(A2 > A3)

            if line3[1] == "B2":
                model.Add(A2 > B2)

        if line3[0] == "A3":
            if line3[1] == "A2":
                model.Add(A3 > A2)

            if line3[1] == "A4":
                model.Add(A3 > A4)

            if line3[1] == "B3":
                model.Add(A3 > B3)

        if line3[0] == "A4":

            if line3[1] == "B4":
                model.Add(A4 > B4)
            if line3[1] == "A3":
                model.Add(A4 > A3)

        if line3[0] == "B1":
            if line3[1] == "A1":
                model.Add(B1 > A1)

            if line3[1] == "C1":
                model.Add(B1 > C1)

            if line3[1] == "B2":
                model.Add(B1 > B2)

        if line3[0] == "B2":
            if line3[1] == "A2":
                model.Add(B2 > A2)

            if line3[1] == "B1":
                model.Add(B2 > B1)

            if line3[1] == "B3":
                model.Add(B2 > B3)

            if line3[1] == "C2":
                model.Add(B2 > C2)

        if line3[0] == "B3":
            if line3[1] == "A3":
                model.Add(B3 > A3)

            if line3[1] == "B2":
                model.Add(B3 > B2)

            if line3[1] == "B4":
                model.Add(B3 > B4)

            if line3[1] == "C3":
                model.Add(B3 > C3)

        if line3[0] == "B4":
            if line3[1] == "A4":
                model.Add(B4 > A4)

            if line3[1] == "B3":
                model.Add(B4 > B3)

            if line3[1] == "C4":
                model.Add(B4 > C4)

        if line3[0] == "C1":
            if line3[1] == "B1":
                model.Add(C1 > B1)

            if line3[1] == "C2":
                model.Add(C1 > C2)

            if line3[1] == "D1":
                model.Add(C1 > D1)

        if line3[0] == "C2":
            if line3[1] == "B2":
                model.Add(C2 > B2)

            if line3[1] == "C1":
                model.Add(C2 > C1)

            if line3[1] == "C3":
                model.Add(C2 > C3)

            if line3[1] == "D2":
                model.Add(C2 > D2)

        if line3[0] == "C3":
            if line3[1] == "B3":
                model.Add(C3 > B3)

            if line3[1] == "C2":
                model.Add(C3 > C2)

            if line3[1] == "C4":
                model.Add(C3 > C4)

            if line3[1] == "D3":
                model.Add(C3 > D3)

        if line3[0] == "C4":

            if line3[1] == "B4":
                model.Add(C4 > B4)

            if line3[1] == "D2":
                model.Add(C4 > D4)

            if line3[1] == "C3":
                model.Add(C4 > C3)

        if line3[0] == "D1":

            if line3[1] == "C1":
                model.Add(D1 > C1)

            if line3[1] == "D2":
                model.Add(D1 > D2)

        if line3[0] == "D2":
            if line3[1] == "D1":
                model.Add(D2 > D1)

            if line3[1] == "C2":
                model.Add(D2 > C2)

            if line3[1] == "D3":
                model.Add(D2 > D3)

        if line3[0] == "D3":
            if line3[1] == "C3":
                model.Add(D3 > C3)

            if line3[1] == "D2":
                model.Add(D3 > D2)

            if line3[1] == "D4":
                model.Add(D3 > D4)
        if line3[0] == "D4":
            if line3[1] == "D3":
                model.Add(D4 > D3)

            if line3[1] == "C4":
                model.Add(D4 > C4)

#line4

    if line4[1].isdigit():
        if line4[0] == "A1":
            model.Add(A1 == int(line4[1]))

        if line4[0] == "A2":
            model.Add(A2 == int(line4[1]))

        if line4[0] == "A3":
            model.Add(A3 == int(line4[1]))

        if line4[0] == "A4":
            model.Add(A4 == int(line4[1]))

        if line4[0] == "B1":
            model.Add(B1 == int(line4[1]))

        if line4[0] == "B2":
            model.Add(B2 == int(line4[1]))

        if line4[0] == "B3":
            model.Add(B3 == int(line4[1]))

        if line4[0] == "B4":
            model.Add(B4 == int(line4[1]))

        if line4[0] == "C1":
            model.Add(C1 == int(line4[1]))

        if line4[0] == "C2":
            model.Add(C2 == int(line4[1]))

        if line4[0] == "C3":
            model.Add(C3 == int(line4[1]))

        if line4[0] == "C4":
            model.Add(C4 == int(line4[1]))

        if line4[0] == "D1":
            model.Add(D1 == int(line4[1]))

        if line4[0] == "D2":
            model.Add(D2 == int(line4[1]))

        if line4[0] == "D3":
            model.Add(D3 == int(line4[1]))

        if line4[0] == "D4":
            model.Add(D4 == int(line4[1]))

    else:
        if line4[0] == "A1":
            if line4[1] == "A2":
                model.Add(A1 > A2)

            if line4[1] == "B1":
                model.Add(A1 > B1)

        if line4[0] == "A2":
            if line4[1] == "A1":
                model.Add(A2 > A1)

            if line4[1] == "A3":
                model.Add(A2 > A3)

            if line4[1] == "B2":
                model.Add(A2 > B2)

        if line4[0] == "A3":
            if line4[1] == "A2":
                model.Add(A3 > A2)

            if line4[1] == "A4":
                model.Add(A3 > A4)

            if line4[1] == "B3":
                model.Add(A3 > B3)

        if line4[0] == "A4":

            if line4[1] == "B4":
                model.Add(A4 > B4)
            if line4[1] == "A3":
                model.Add(A4 > A3)

        if line4[0] == "B1":
            if line4[1] == "A1":
                model.Add(B1 > A1)

            if line4[1] == "C1":
                model.Add(B1 > C1)

            if line4[1] == "B2":
                model.Add(B1 > B2)

        if line4[0] == "B2":
            if line4[1] == "A2":
                model.Add(B2 > A2)

            if line4[1] == "B1":
                model.Add(B2 > B1)

            if line4[1] == "B3":
                model.Add(B2 > B3)

            if line4[1] == "C2":
                model.Add(B2 > C2)

        if line4[0] == "B3":
            if line4[1] == "A3":
                model.Add(B3 > A3)

            if line4[1] == "B2":
                model.Add(B3 > B2)

            if line4[1] == "B4":
                model.Add(B3 > B4)

            if line4[1] == "C3":
                model.Add(B3 > C3)

        if line4[0] == "B4":
            if line4[1] == "A4":
                model.Add(B4 > A4)

            if line4[1] == "B3":
                model.Add(B4 > B3)

            if line4[1] == "C4":
                model.Add(B4 > C4)

        if line4[0] == "C1":
            if line4[1] == "B1":
                model.Add(C1 > B1)

            if line4[1] == "C2":
                model.Add(C1 > C2)

            if line4[1] == "D1":
                model.Add(C1 > D1)

        if line4[0] == "C2":
            if line4[1] == "B2":
                model.Add(C2 > B2)

            if line4[1] == "C1":
                model.Add(C2 > C1)

            if line4[1] == "C3":
                model.Add(C2 > C3)

            if line4[1] == "D2":
                model.Add(C2 > D2)

        if line4[0] == "C3":
            if line4[1] == "B3":
                model.Add(C3 > B3)

            if line4[1] == "C2":
                model.Add(C3 > C2)

            if line4[1] == "C4":
                model.Add(C3 > C4)

            if line4[1] == "D3":
                model.Add(C3 > D3)

        if line4[0] == "C4":

            if line4[1] == "B4":
                model.Add(C4 > B4)

            if line4[1] == "D2":
                model.Add(C4 > D4)

            if line4[1] == "C3":
                model.Add(C4 > C3)

        if line4[0] == "D1":

            if line4[1] == "C1":
                model.Add(D1 > C1)

            if line4[1] == "D2":
                model.Add(D1 > D2)

        if line4[0] == "D2":
            if line4[1] == "D1":
                model.Add(D2 > D1)

            if line4[1] == "C2":
                model.Add(D2 > C2)

            if line4[1] == "D3":
                model.Add(D2 > D3)

        if line4[0] == "D3":
            if line4[1] == "C3":
                model.Add(D3 > C3)

            if line4[1] == "D2":
                model.Add(D3 > D2)

            if line4[1] == "D4":
                model.Add(D3 > D4)
        if line4[0] == "D4":
            if line4[1] == "D3":
                model.Add(D4 > D3)

            if line4[1] == "C4":
                model.Add(D4 > C4)

#line5

    if line5[1].isdigit():
        if line5[0] == "A1":
            model.Add(A1 == int(line5[1]))

        if line5[0] == "A2":
            model.Add(A2 == int(line5[1]))

        if line5[0] == "A3":
            model.Add(A3 == int(line5[1]))

        if line5[0] == "A4":
            model.Add(A4 == int(line5[1]))

        if line5[0] == "B1":
            model.Add(B1 == int(line5[1]))

        if line5[0] == "B2":
            model.Add(B2 == int(line5[1]))

        if line5[0] == "B3":
            model.Add(B3 == int(line5[1]))

        if line5[0] == "B4":
            model.Add(B4 == int(line5[1]))

        if line5[0] == "C1":
            model.Add(C1 == int(line5[1]))

        if line5[0] == "C2":
            model.Add(C2 == int(line5[1]))

        if line5[0] == "C3":
            model.Add(C3 == int(line5[1]))

        if line5[0] == "C4":
            model.Add(C4 == int(line5[1]))

        if line5[0] == "D1":
            model.Add(D1 == int(line5[1]))

        if line5[0] == "D2":
            model.Add(D2 == int(line5[1]))

        if line5[0] == "D3":
            model.Add(D3 == int(line5[1]))

        if line5[0] == "D4":
            model.Add(D4 == int(line5[1]))

    else:
        if line5[0] == "A1":
            if line5[1] == "A2":
                model.Add(A1 > A2)

            if line5[1] == "B1":
                model.Add(A1 > B1)

        if line5[0] == "A2":
            if line5[1] == "A1":
                model.Add(A2 > A1)

            if line5[1] == "A3":
                model.Add(A2 > A3)

            if line5[1] == "B2":
                model.Add(A2 > B2)

        if line5[0] == "A3":
            if line5[1] == "A2":
                model.Add(A3 > A2)

            if line5[1] == "A4":
                model.Add(A3 > A4)

            if line5[1] == "B3":
                model.Add(A3 > B3)

        if line5[0] == "A4":

            if line5[1] == "B4":
                model.Add(A4 > B4)
            if line5[1] == "A3":
                model.Add(A4 > A3)

        if line5[0] == "B1":
            if line5[1] == "A1":
                model.Add(B1 > A1)

            if line5[1] == "C1":
                model.Add(B1 > C1)

            if line5[1] == "B2":
                model.Add(B1 > B2)

        if line5[0] == "B2":
            if line5[1] == "A2":
                model.Add(B2 > A2)

            if line5[1] == "B1":
                model.Add(B2 > B1)

            if line5[1] == "B3":
                model.Add(B2 > B3)

            if line5[1] == "C2":
                model.Add(B2 > C2)

        if line5[0] == "B3":
            if line5[1] == "A3":
                model.Add(B3 > A3)

            if line5[1] == "B2":
                model.Add(B3 > B2)

            if line5[1] == "B4":
                model.Add(B3 > B4)

            if line5[1] == "C3":
                model.Add(B3 > C3)

        if line5[0] == "B4":
            if line5[1] == "A4":
                model.Add(B4 > A4)

            if line5[1] == "B3":
                model.Add(B4 > B3)

            if line5[1] == "C4":
                model.Add(B4 > C4)

        if line5[0] == "C1":
            if line5[1] == "B1":
                model.Add(C1 > B1)

            if line5[1] == "C2":
                model.Add(C1 > C2)

            if line5[1] == "D1":
                model.Add(C1 > D1)

        if line5[0] == "C2":
            if line5[1] == "B2":
                model.Add(C2 > B2)

            if line5[1] == "C1":
                model.Add(C2 > C1)

            if line5[1] == "C3":
                model.Add(C2 > C3)

            if line5[1] == "D2":
                model.Add(C2 > D2)

        if line5[0] == "C3":
            if line5[1] == "B3":
                model.Add(C3 > B3)

            if line5[1] == "C2":
                model.Add(C3 > C2)

            if line5[1] == "C4":
                model.Add(C3 > C4)

            if line5[1] == "D3":
                model.Add(C3 > D3)

        if line5[0] == "C4":

            if line5[1] == "B4":
                model.Add(C4 > B4)

            if line5[1] == "D2":
                model.Add(C4 > D4)

            if line5[1] == "C3":
                model.Add(C4 > C3)

        if line5[0] == "D1":

            if line5[1] == "C1":
                model.Add(D1 > C1)

            if line5[1] == "D2":
                model.Add(D1 > D2)

        if line5[0] == "D2":
            if line5[1] == "D1":
                model.Add(D2 > D1)

            if line5[1] == "C2":
                model.Add(D2 > C2)

            if line5[1] == "D3":
                model.Add(D2 > D3)

        if line5[0] == "D3":
            if line5[1] == "C3":
                model.Add(D3 > C3)

            if line5[1] == "D2":
                model.Add(D3 > D2)

            if line5[1] == "D4":
                model.Add(D3 > D4)
        if line5[0] == "D4":
            if line5[1] == "D3":
                model.Add(D4 > D3)

            if line5[1] == "C4":
                model.Add(D4 > C4)


#line6

    if line6[1].isdigit():
        if line6[0] == "A1":
            model.Add(A1 == int(line6[1]))

        if line6[0] == "A2":
            model.Add(A2 == int(line6[1]))

        if line6[0] == "A3":
            model.Add(A3 == int(line6[1]))

        if line6[0] == "A4":
            model.Add(A4 == int(line6[1]))

        if line6[0] == "B1":
            model.Add(B1 == int(line6[1]))

        if line6[0] == "B2":
            model.Add(B2 == int(line6[1]))

        if line6[0] == "B3":
            model.Add(B3 == int(line6[1]))

        if line6[0] == "B4":
            model.Add(B4 == int(line6[1]))

        if line6[0] == "C1":
            model.Add(C1 == int(line6[1]))

        if line6[0] == "C2":
            model.Add(C2 == int(line6[1]))

        if line6[0] == "C3":
            model.Add(C3 == int(line6[1]))

        if line6[0] == "C4":
            model.Add(C4 == int(line6[1]))

        if line6[0] == "D1":
            model.Add(D1 == int(line6[1]))

        if line6[0] == "D2":
            model.Add(D2 == int(line6[1]))

        if line6[0] == "D3":
            model.Add(D3 == int(line6[1]))

        if line6[0] == "D4":
            model.Add(D4 == int(line6[1]))

    else:
        if line6[0] == "A1":
            if line6[1] == "A2":
                model.Add(A1 > A2)

            if line6[1] == "B1":
                model.Add(A1 > B1)

        if line6[0] == "A2":
            if line6[1] == "A1":
                model.Add(A2 > A1)

            if line6[1] == "A3":
                model.Add(A2 > A3)

            if line6[1] == "B2":
                model.Add(A2 > B2)

        if line6[0] == "A3":
            if line6[1] == "A2":
                model.Add(A3 > A2)

            if line6[1] == "A4":
                model.Add(A3 > A4)

            if line6[1] == "B3":
                model.Add(A3 > B3)

        if line6[0] == "A4":

            if line6[1] == "B4":
                model.Add(A4 > B4)
            if line6[1] == "A3":
                model.Add(A4 > A3)

        if line6[0] == "B1":
            if line6[1] == "A1":
                model.Add(B1 > A1)

            if line6[1] == "C1":
                model.Add(B1 > C1)

            if line6[1] == "B2":
                model.Add(B1 > B2)

        if line6[0] == "B2":
            if line6[1] == "A2":
                model.Add(B2 > A2)

            if line6[1] == "B1":
                model.Add(B2 > B1)

            if line6[1] == "B3":
                model.Add(B2 > B3)

            if line6[1] == "C2":
                model.Add(B2 > C2)

        if line6[0] == "B3":
            if line6[1] == "A3":
                model.Add(B3 > A3)

            if line6[1] == "B2":
                model.Add(B3 > B2)

            if line6[1] == "B4":
                model.Add(B3 > B4)

            if line6[1] == "C3":
                model.Add(B3 > C3)

        if line6[0] == "B4":
            if line6[1] == "A4":
                model.Add(B4 > A4)

            if line6[1] == "B3":
                model.Add(B4 > B3)

            if line6[1] == "C4":
                model.Add(B4 > C4)

        if line6[0] == "C1":
            if line6[1] == "B1":
                model.Add(C1 > B1)

            if line6[1] == "C2":
                model.Add(C1 > C2)

            if line6[1] == "D1":
                model.Add(C1 > D1)

        if line6[0] == "C2":
            if line6[1] == "B2":
                model.Add(C2 > B2)

            if line6[1] == "C1":
                model.Add(C2 > C1)

            if line6[1] == "C3":
                model.Add(C2 > C3)

            if line6[1] == "D2":
                model.Add(C2 > D2)

        if line6[0] == "C3":
            if line6[1] == "B3":
                model.Add(C3 > B3)

            if line6[1] == "C2":
                model.Add(C3 > C2)

            if line6[1] == "C4":
                model.Add(C3 > C4)

            if line6[1] == "D3":
                model.Add(C3 > D3)

        if line6[0] == "C4":

            if line6[1] == "B4":
                model.Add(C4 > B4)

            if line6[1] == "D2":
                model.Add(C4 > D4)

            if line6[1] == "C3":
                model.Add(C4 > C3)

        if line6[0] == "D1":

            if line6[1] == "C1":
                model.Add(D1 > C1)

            if line6[1] == "D2":
                model.Add(D1 > D2)

        if line6[0] == "D2":
            if line6[1] == "D1":
                model.Add(D2 > D1)

            if line6[1] == "C2":
                model.Add(D2 > C2)

            if line6[1] == "D3":
                model.Add(D2 > D3)

        if line6[0] == "D3":
            if line6[1] == "C3":
                model.Add(D3 > C3)

            if line6[1] == "D2":
                model.Add(D3 > D2)

            if line6[1] == "D4":
                model.Add(D3 > D4)
        if line6[0] == "D4":
            if line6[1] == "D3":
                model.Add(D4 > D3)

            if line6[1] == "C4":
                model.Add(D4 > C4)

    # Creates a solver and solves the model.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    if status == cp_model.FEASIBLE:
        A1 = solver.Value(A1)
        A2 = solver.Value(A2)
        A3 = solver.Value(A3)
        A4 = solver.Value(A4)
        B1 = solver.Value(B1)
        B2 = solver.Value(B2)
        B3 = solver.Value(B3)
        B4 = solver.Value(B4)
        C1 = solver.Value(C1)
        C2 = solver.Value(C2)
        C3 = solver.Value(C3)
        C4 = solver.Value(C4)
        D1 = solver.Value(D1)
        D2 = solver.Value(D2)
        D3 = solver.Value(D3)
        D4 = solver.Value(D4)

        #print(A1,",",A2,",",A3,",",A4)
        #print(B1,",",B2,",",B3,",",B4)
        #print(C1,",",C2,",",C3,",",C4)
        #print(D1,",",D2,",",D3,",",D4)

        list = [A1, A2, A3, A4]
        list2 = [B1, B2, B3, B4]
        list3 = [C1, C2, C3, C4]
        list4 = [D1, D2, D3, D4]

        for i in list:
            output.write(str(i))
            if i == list[3]:
                break
            else:
                output.write(",")
        output.write("\n")

        for i in list2:
            output.write(str(i))
            if i == list2[3]:
                break
            else:
                output.write(",")
        output.write("\n")

        for i in list3:
            output.write(str(i))
            if i == list3[3]:
                break
            else:
                output.write(",")

        output.write("\n")

        for i in list4:
            output.write(str(i))
            if i == list4[3]:
                break
            else:
                output.write(",")
Beispiel #16
0
def steel_mill_slab_with_valid_slabs(problem, break_symmetries, output_proto):
    """Solves the Steel Mill Slab Problem."""
    ### Load problem.
    (num_slabs, capacities, num_colors, orders) = build_problem(problem)

    num_orders = len(orders)
    num_capacities = len(capacities)
    all_slabs = range(num_slabs)
    all_colors = range(num_colors)
    all_orders = range(len(orders))
    print('Solving steel mill with %i orders, %i slabs, and %i capacities' %
          (num_orders, num_slabs, num_capacities - 1))

    # Compute auxilliary data.
    widths = [x[0] for x in orders]
    colors = [x[1] for x in orders]
    max_capacity = max(capacities)
    loss_array = [
        min(x for x in capacities if x >= c) - c
        for c in range(max_capacity + 1)
    ]
    max_loss = max(loss_array)

    ### Model problem.

    # Create the model and the decision variables.
    model = cp_model.CpModel()
    assign = [[
        model.NewBoolVar('assign_%i_to_slab_%i' % (o, s)) for s in all_slabs
    ] for o in all_orders]
    loads = [
        model.NewIntVar(0, max_capacity, 'load_%i' % s) for s in all_slabs
    ]
    losses = [model.NewIntVar(0, max_loss, 'loss_%i' % s) for s in all_slabs]

    unsorted_valid_slabs = collect_valid_slabs_dp(capacities, colors, widths,
                                                  loss_array)
    # Sort slab by descending load/loss. Remove duplicates.
    valid_slabs = sorted(unsorted_valid_slabs,
                         key=lambda c: 1000 * c[-1] + c[-2])

    for s in all_slabs:
        model.AddAllowedAssignments([assign[o][s] for o in all_orders] +
                                    [losses[s], loads[s]], valid_slabs)

    # Orders are assigned to one slab.
    for o in all_orders:
        model.Add(sum(assign[o]) == 1)

    # Redundant constraint (sum of loads == sum of widths).
    model.Add(sum(loads) == sum(widths))

    # Symmetry breaking.
    for s in range(num_slabs - 1):
        model.Add(loads[s] >= loads[s + 1])

    # Collect equivalent orders.
    if break_symmetries:
        print('Breaking symmetries')
        width_to_unique_color_order = {}
        ordered_equivalent_orders = []
        orders_per_color = [[o for o in all_orders if colors[o] == c + 1]
                            for c in all_colors]
        for c in all_colors:
            colored_orders = orders_per_color[c]
            if not colored_orders:
                continue
            if len(colored_orders) == 1:
                o = colored_orders[0]
                w = widths[o]
                if w not in width_to_unique_color_order:
                    width_to_unique_color_order[w] = [o]
                else:
                    width_to_unique_color_order[w].append(o)
            else:
                local_width_to_order = {}
                for o in colored_orders:
                    w = widths[o]
                    if w not in local_width_to_order:
                        local_width_to_order[w] = []
                        local_width_to_order[w].append(o)
                for w, os in local_width_to_order.items():
                    if len(os) > 1:
                        for p in range(len(os) - 1):
                            ordered_equivalent_orders.append(
                                (os[p], os[p + 1]))
        for w, os in width_to_unique_color_order.items():
            if len(os) > 1:
                for p in range(len(os) - 1):
                    ordered_equivalent_orders.append((os[p], os[p + 1]))

        # Create position variables if there are symmetries to be broken.
        if ordered_equivalent_orders:
            print('  - creating %i symmetry breaking constraints' %
                  len(ordered_equivalent_orders))
            positions = {}
            for p in ordered_equivalent_orders:
                if p[0] not in positions:
                    positions[p[0]] = model.NewIntVar(
                        0, num_slabs - 1, 'position_of_slab_%i' % p[0])
                    model.AddMapDomain(positions[p[0]], assign[p[0]])
                if p[1] not in positions:
                    positions[p[1]] = model.NewIntVar(
                        0, num_slabs - 1, 'position_of_slab_%i' % p[1])
                    model.AddMapDomain(positions[p[1]], assign[p[1]])
                    # Finally add the symmetry breaking constraint.
                model.Add(positions[p[0]] <= positions[p[1]])

    # Objective.
    model.Minimize(sum(losses))

    print('Model created')

    # Output model proto to file.
    if output_proto:
        output_file = open(output_proto, 'w')
        output_file.write(str(model.Proto()))
        output_file.close()

    ### Solve model.
    solver = cp_model.CpSolver()
    solver.num_search_workers = 8
    solution_printer = SteelMillSlabSolutionPrinter(orders, assign, loads,
                                                    losses)
    status = solver.SolveWithSolutionCallback(model, solution_printer)

    ### Output the solution.
    if status == cp_model.OPTIMAL:
        print('Loss = %i, time = %.2f s, %i conflicts' %
              (solver.ObjectiveValue(), solver.WallTime(),
               solver.NumConflicts()))
    else:
        print('No solution')
Beispiel #17
0
def MinimalJobShop():
    """Minimal jobshop problem."""
    # Create the model.
    model = cp_model.CpModel()

    machines_count = 3
    jobs_count = 3
    all_machines = range(0, machines_count)
    all_jobs = range(0, jobs_count)
    # Define data.
    machines = [[0, 1, 2], [0, 2, 1], [1, 2]]

    processing_times = [[3, 2, 2], [2, 1, 4], [4, 3]]
    # Computes horizon.
    horizon = 0
    for job in all_jobs:
        horizon += sum(processing_times[job])

    task_type = collections.namedtuple('task_type', 'start end interval')
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index')

    # Creates jobs.
    all_tasks = {}
    for job in all_jobs:
        for index in range(0, len(machines[job])):
            start_var = model.NewIntVar(0, horizon,
                                        'start_%i_%i' % (job, index))
            duration = processing_times[job][index]
            end_var = model.NewIntVar(0, horizon, 'end_%i_%i' % (job, index))
            interval_var = model.NewIntervalVar(
                start_var, duration, end_var, 'interval_%i_%i' % (job, index))
            all_tasks[(job, index)] = task_type(start=start_var,
                                                end=end_var,
                                                interval=interval_var)

    # Creates sequence variables and add disjunctive constraints.
    for machine in all_machines:
        intervals = []
        for job in all_jobs:
            for index in range(0, len(machines[job])):
                if machines[job][index] == machine:
                    intervals.append(all_tasks[(job, index)].interval)
        model.AddNoOverlap(intervals)

    # Add precedence contraints.
    for job in all_jobs:
        for index in range(0, len(machines[job]) - 1):
            model.Add(all_tasks[(job, index +
                                 1)].start >= all_tasks[(job, index)].end)

    # Makespan objective.
    obj_var = model.NewIntVar(0, horizon, 'makespan')
    model.AddMaxEquality(
        obj_var,
        [all_tasks[(job, len(machines[job]) - 1)].end for job in all_jobs])
    model.Minimize(obj_var)

    # Solve model.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    if status == cp_model.OPTIMAL:
        # Print out makespan.
        print('Optimal Schedule Length: %i' % solver.ObjectiveValue())
        print()

        # Create one list of assigned tasks per machine.
        assigned_jobs = [[] for _ in range(machines_count)]
        for job in all_jobs:
            for index in range(len(machines[job])):
                machine = machines[job][index]
                assigned_jobs[machine].append(
                    assigned_task_type(start=solver.Value(
                        all_tasks[(job, index)].start),
                                       job=job,
                                       index=index))

        disp_col_width = 10
        sol_line = ''
        sol_line_tasks = ''

        print('Optimal Schedule', '\n')

        for machine in all_machines:
            # Sort by starting time.
            assigned_jobs[machine].sort()
            sol_line += 'Machine ' + str(machine) + ': '
            sol_line_tasks += 'Machine ' + str(machine) + ': '

            for assigned_task in assigned_jobs[machine]:
                name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)
                # Add spaces to output to align columns.
                sol_line_tasks += name + ' ' * (disp_col_width - len(name))
                start = assigned_task.start
                duration = processing_times[assigned_task.job][
                    assigned_task.index]

                sol_tmp = '[%i,%i]' % (start, start + duration)
                # Add spaces to output to align columns.
                sol_line += sol_tmp + ' ' * (disp_col_width - len(sol_tmp))

            sol_line += '\n'
            sol_line_tasks += '\n'

        print(sol_line_tasks)
        print('Time Intervals for task_types\n')
        print(sol_line)
Beispiel #18
0
def steel_mill_slab_with_column_generation(problem, output_proto):
    """Solves the Steel Mill Slab Problem."""
    ### Load problem.
    (num_slabs, capacities, _, orders) = build_problem(problem)

    num_orders = len(orders)
    num_capacities = len(capacities)
    all_orders = range(len(orders))
    print('Solving steel mill with %i orders, %i slabs, and %i capacities' %
          (num_orders, num_slabs, num_capacities - 1))

    # Compute auxilliary data.
    widths = [x[0] for x in orders]
    colors = [x[1] for x in orders]
    max_capacity = max(capacities)
    loss_array = [
        min(x for x in capacities if x >= c) - c
        for c in range(max_capacity + 1)
    ]

    ### Model problem.

    # Generate all valid slabs (columns)
    unsorted_valid_slabs = collect_valid_slabs_dp(capacities, colors, widths,
                                                  loss_array)

    # Sort slab by descending load/loss. Remove duplicates.
    valid_slabs = sorted(unsorted_valid_slabs,
                         key=lambda c: 1000 * c[-1] + c[-2])
    all_valid_slabs = range(len(valid_slabs))

    # create model and decision variables.
    model = cp_model.CpModel()
    selected = [model.NewBoolVar('selected_%i' % i) for i in all_valid_slabs]

    for order_id in all_orders:
        model.Add(
            sum(selected[i] for i, slab in enumerate(valid_slabs)
                if slab[order_id]) == 1)

    # Redundant constraint (sum of loads == sum of widths).
    model.Add(
        sum(selected[i] * valid_slabs[i][-1]
            for i in all_valid_slabs) == sum(widths))

    # Objective.
    model.Minimize(
        sum(selected[i] * valid_slabs[i][-2] for i in all_valid_slabs))

    print('Model created')

    # Output model proto to file.
    if output_proto:
        output_file = open(output_proto, 'w')
        output_file.write(str(model.Proto()))
        output_file.close()

    ### Solve model.
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = 8
    solution_printer = cp_model.ObjectiveSolutionPrinter()
    status = solver.SolveWithSolutionCallback(model, solution_printer)

    ### Output the solution.
    if status in (cp_model.OPTIMAL, cp_model.FEASIBLE):
        print('Loss = %i, time = %.2f s, %i conflicts' %
              (solver.ObjectiveValue(), solver.WallTime(),
               solver.NumConflicts()))
    else:
        print('No solution')
def cover_rectangle(num_squares):
    """Try to fill the rectangle with a given number of squares."""
    size_x = 72
    size_y = 37

    model = cp_model.CpModel()

    areas = []
    sizes = []
    x_intervals = []
    y_intervals = []
    x_starts = []
    y_starts = []

    # Creates intervals for the NoOverlap2D and size variables.
    for i in range(num_squares):
        size = model.NewIntVar(1, size_y, 'size_%i' % i)
        startx = model.NewIntVar(0, size_x, 'sx_%i' % i)
        endx = model.NewIntVar(0, size_x, 'ex_%i' % i)
        starty = model.NewIntVar(0, size_y, 'sy_%i' % i)
        endy = model.NewIntVar(0, size_y, 'ey_%i' % i)

        interval_x = model.NewIntervalVar(startx, size, endx, 'ix_%i' % i)
        interval_y = model.NewIntervalVar(starty, size, endy, 'iy_%i' % i)

        area = model.NewIntVar(1, size_y * size_y, 'area_%i' % i)
        model.AddProdEquality(area, [size, size])

        areas.append(area)
        x_intervals.append(interval_x)
        y_intervals.append(interval_y)
        sizes.append(size)
        x_starts.append(startx)
        y_starts.append(starty)

    # Main constraint.
    model.AddNoOverlap2D(x_intervals, y_intervals)

    # Redundant constraints.
    model.AddCumulative(x_intervals, sizes, size_y)
    model.AddCumulative(y_intervals, sizes, size_x)

    # Forces the rectangle to be exactly covered.
    model.Add(sum(areas) == size_x * size_y)

    # Symmetry breaking 1: sizes are ordered.
    for i in range(num_squares - 1):
        model.Add(sizes[i] <= sizes[i + 1])

    # Symmetry breaking 2: first square in one quadrant.
    model.Add(x_starts[0] < 36)
    model.Add(y_starts[0] < 19)

    # Creates a solver and solves.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    print('%s found in %0.2fs' %
          (solver.StatusName(status), solver.WallTime()))

    # Prints solution.
    if status == cp_model.FEASIBLE:
        display = [[' ' for _ in range(size_x)] for _ in range(size_y)]
        for i in range(num_squares):
            sol_x = solver.Value(x_starts[i])
            sol_y = solver.Value(y_starts[i])
            sol_s = solver.Value(sizes[i])
            char = format(i, '01x')
            for j in range(sol_s):
                for k in range(sol_s):
                    if display[sol_y + j][sol_x + k] != ' ':
                        print('ERROR between %s and %s' %
                              (display[sol_y + j][sol_x + k], char))
                    display[sol_y + j][sol_x + k] = char

        for line in range(size_y):
            print(' '.join(display[line]))
    return status == cp_model.FEASIBLE
Beispiel #20
0
def main():
    """Create the shift scheduling model and solve it."""
    # Create the model.
    model = cp_model.CpModel()

    #
    # data
    #
    num_vendors = 9
    num_hours = 10
    num_work_types = 1

    traffic = [100, 500, 100, 200, 320, 300, 200, 220, 300, 120]
    max_traffic_per_vendor = 100

    # Last columns are :
    #   index_of_the_schedule, sum of worked hours (per work type).
    # The index is useful for branching.
    possible_schedules = [[1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0,
                           8], [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1,
                                4], [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 2,
                                     5], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 4],
                          [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 4,
                           3], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0]]

    num_possible_schedules = len(possible_schedules)
    selected_schedules = []
    vendors_stat = []
    hours_stat = []

    # Auxiliary data
    min_vendors = [t // max_traffic_per_vendor for t in traffic]
    all_vendors = range(num_vendors)
    all_hours = range(num_hours)

    #
    # declare variables
    #
    x = {}

    for v in all_vendors:
        tmp = []
        for h in all_hours:
            x[v, h] = model.NewIntVar(0, num_work_types, 'x[%i,%i]' % (v, h))
            tmp.append(x[v, h])
        selected_schedule = model.NewIntVar(0, num_possible_schedules - 1,
                                            's[%i]' % v)
        hours = model.NewIntVar(0, num_hours, 'h[%i]' % v)
        selected_schedules.append(selected_schedule)
        vendors_stat.append(hours)
        tmp.append(selected_schedule)
        tmp.append(hours)

        model.AddAllowedAssignments(tmp, possible_schedules)

    #
    # Statistics and constraints for each hour
    #
    for h in all_hours:
        workers = model.NewIntVar(0, 1000, 'workers[%i]' % h)
        model.Add(workers == sum(x[v, h] for v in all_vendors))
        hours_stat.append(workers)
        model.Add(workers * max_traffic_per_vendor >= traffic[h])

    #
    # Redundant constraint: sort selected_schedules
    #
    for v in range(num_vendors - 1):
        model.Add(selected_schedules[v] <= selected_schedules[v + 1])

    # Solve model.
    solver = cp_model.CpSolver()
    solver.parameters.enumerate_all_solutions = True
    solution_printer = SolutionPrinter(num_vendors, num_hours,
                                       possible_schedules, selected_schedules,
                                       hours_stat, min_vendors)
    status = solver.Solve(model, solution_printer)
    print('Status = %s' % solver.StatusName(status))

    print('Statistics')
    print('  - conflicts : %i' % solver.NumConflicts())
    print('  - branches  : %i' % solver.NumBranches())
    print('  - wall time : %f s' % solver.WallTime())
    print(
        '  - number of solutions found: %i' % solution_printer.solution_count())
def main():
    # Data
    # [START data]
    costs = [
        [90, 76, 75, 70, 50, 74, 12, 68],
        [35, 85, 55, 65, 48, 101, 70, 83],
        [125, 95, 90, 105, 59, 120, 36, 73],
        [45, 110, 95, 115, 104, 83, 37, 71],
        [60, 105, 80, 75, 59, 62, 93, 88],
        [45, 65, 110, 95, 47, 31, 81, 34],
        [38, 51, 107, 41, 69, 99, 115, 48],
        [47, 85, 57, 71, 92, 77, 109, 36],
        [39, 63, 97, 49, 118, 56, 92, 61],
        [47, 101, 71, 60, 88, 109, 52, 90],
    ]
    num_workers = len(costs)
    num_tasks = len(costs[0])

    task_sizes = [10, 7, 3, 12, 15, 4, 11, 5]
    # Maximum total of task sizes for any worker
    total_size_max = 15
    # [END data]

    # Model
    # [START model]
    model = cp_model.CpModel()
    # [END model]

    # Variables
    # [START variables]
    x = {}
    for worker in range(num_workers):
        for task in range(num_tasks):
            x[worker, task] = model.NewBoolVar(f'x[{worker},{task}]')
    # [END variables]

    # Constraints
    # [START constraints]
    # Each worker is assigned to at most one task.
    for worker in range(num_workers):
        model.Add(
            sum(task_sizes[task] * x[worker, task]
                for task in range(num_tasks)) <= total_size_max)

    # Each task is assigned to exactly one worker.
    for task in range(num_tasks):
        model.AddExactlyOne([x[worker, task] for worker in range(num_workers)])
    # [END constraints]

    # Objective
    # [START objective]
    objective_terms = []
    for worker in range(num_workers):
        for task in range(num_tasks):
            objective_terms.append(costs[worker][task] * x[worker, task])
    model.Minimize(sum(objective_terms))
    # [END objective]

    # Solve
    # [START solve]
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    # [END solve]

    # Print solution.
    # [START print_solution]
    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print(f'Total cost = {solver.ObjectiveValue()}\n')
        for worker in range(num_workers):
            for task in range(num_tasks):
                if solver.BooleanValue(x[worker, task]):
                    print(f'Worker {worker} assigned to task {task}.' +
                          f' Cost = {costs[worker][task]}')
    else:
        print('No solution found.')
Beispiel #22
0
def poma_scheduler(self):
    # Database model creation
    schedule = skynet_models.Schedule.objects.create(celery_id=self.request.id)

    # We run the dispatcher, to update previous tasks status
    tareas.octoprint_task_dispatcher()

    # Data type definition used for scheduling
    task_data_type = collections.namedtuple(
        'task_data', 'piece_id processing_time deadline copy processing_on')
    tasks_data = []

    # Pending pieces
    for p in skynet_models.Piece.objects.all():
        if p.quote_ready() and not p.cancelled:
            for copy in range(0, p.queued_pieces):
                tasks_data.append(
                    task_data_type(
                        p.id, int(p.get_build_time()),
                        max(int(p.get_deadline_from_now()),
                            int(p.get_build_time())), copy, None))

    # Machines
    available_machines = [
        p for p in skynet_models.Printer.objects.all()
        if p.printer_connection_enabled
    ]
    machines_count = len(available_machines)

    # Create the model.
    model = cp_model.CpModel()

    # Machines queue definition
    machines_queue = {}
    machines_corresp_to_db = {}
    for id, m in enumerate(available_machines):
        machines_queue[id] = []
        machines_corresp_to_db[id] = m.id

    # Pieces in progress
    for m in available_machines:
        if m.connection.active_task is not None:
            at = m.connection.active_task
            if not at.finished:
                tasks_data.append(
                    task_data_type('OT{}'.format(at.id), int(at.time_left),
                                   int(at.time_left), 0, [
                                       x
                                       for x in machines_corresp_to_db.keys()
                                       if machines_corresp_to_db[x] == m.id
                                   ][0]))

    # Horizon definition
    horizon = max(sum([t.processing_time for t in tasks_data]), 3600 * 24)
    tasks_count = len(tasks_data)

    # Forbidden zones definition
    bounds = get_formatted_forbidden_bounds(horizon)

    print(tasks_data)
    # Tasks creation
    task_type = collections.namedtuple('task',
                                       'id data start end interval machine')
    task_optional_type = collections.namedtuple(
        'task_optional', 'id start end interval machine flag')
    all_tasks = []
    task_queue = {}

    for id, task in enumerate(tasks_data):
        start_var = model.NewIntVar(0, horizon, 'start_{id}'.format(id=id))
        end_var = model.NewIntVar(0, horizon, 'end_{id}'.format(id=id))
        interval = model.NewIntervalVar(start_var, task.processing_time,
                                        end_var, 'interval_{id}'.format(id=id))
        machine_var = model.NewIntVar(0, machines_count,
                                      'machine_{id}'.format(id=id))
        all_tasks.append(
            task_type(id=id,
                      data=task,
                      start=start_var,
                      end=end_var,
                      interval=interval,
                      machine=machine_var))
        # We create a copy of each interval, on each machine, as an OptionalIntervalVar, if we can print it on it
        task_queue[id] = []
        for m in machines_queue.keys():
            # Consider possible tasks and present tasks
            ## Possible tasks
            if task.processing_on is None:
                # Printer compatibility check
                if print_piece_on_printer_check(
                        skynet_models.Piece.objects.get(id=task.piece_id),
                        skynet_models.Printer.objects.get(
                            id=machines_corresp_to_db[m])):
                    start_var_o = model.NewIntVar(
                        0, horizon,
                        'start_{id}_on_{machine}'.format(id=id, machine=m))
                    end_var_o = model.NewIntVar(
                        0, horizon, 'end_{id}_on_{machine}'.format(id=id,
                                                                   machine=m))
                    flag = model.NewBoolVar('perform_{id}_on_{machine}'.format(
                        id=id, machine=m))
                    task_queue[id].append(flag)
                    interval_o = model.NewOptionalIntervalVar(
                        start_var_o, task.processing_time, end_var_o, flag,
                        'interval_{id}_on_{machine}'.format(id=id, machine=m))
                    machines_queue[m].append(
                        task_optional_type(id=id,
                                           start=start_var_o,
                                           end=end_var_o,
                                           interval=interval_o,
                                           machine=m,
                                           flag=flag))

                    ## We only propagate the constraint if the task is performed on the machine
                    model.Add(start_var == start_var_o).OnlyEnforceIf(flag)
                    model.Add(machine_var == m).OnlyEnforceIf(flag)
            ## Present tasks
            else:
                if m == task.processing_on:
                    start_var_o = model.NewIntVar(
                        0, horizon,
                        'start_{id}_on_{machine}'.format(id=id, machine=m))
                    end_var_o = model.NewIntVar(
                        0, horizon, 'end_{id}_on_{machine}'.format(id=id,
                                                                   machine=m))
                    flag = model.NewBoolVar('perform_{id}_on_{machine}'.format(
                        id=id, machine=m))
                    task_queue[id].append(flag)
                    interval_o = model.NewOptionalIntervalVar(
                        start_var_o, task.processing_time, end_var_o, flag,
                        'interval_{id}_on_{machine}'.format(id=id, machine=m))
                    machines_queue[m].append(
                        task_optional_type(id=id,
                                           start=start_var_o,
                                           end=end_var_o,
                                           interval=interval_o,
                                           machine=m,
                                           flag=flag))

                    ## We only propagate the constraint if the task is performed on the machine
                    model.Add(start_var == start_var_o)
                    model.Add(machine_var == m)
                    model.Add(start_var_o == 0)
                    model.Add(flag == True)

    # Constrains

    ## Task_i is performed somewhere (and only on one machine)
    for t in task_queue.keys():
        model.AddBoolXOr(task_queue[t])

    ## Disjunctive constrains
    for m in range(machines_count):
        model.AddNoOverlap([t.interval for t in machines_queue[m]])

    ## Jobs should be ended by deadline
    for task_i in all_tasks:
        model.Add(task_i.end <= task_i.data.deadline)

    ## Forbidden zones constrains
    for task in all_tasks:
        model.AddLinearConstraintWithBounds([(task.start, 1)], bounds)

    # Makespan objective.
    obj_var = model.NewIntVar(0, horizon, 'makespan')
    model.AddMaxEquality(obj_var, [task.end for task in all_tasks])

    model.Minimize(obj_var)

    # Solve model.
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = os.cpu_count()
    # Solver solution limit
    solver.parameters.max_time_in_seconds = 3600 * 2
    status = solver.SolveWithSolutionCallback(model,
                                              CpModelSolutionCallback(10**5))
    print('Model validated: {}'.format(status == cp_model.OPTIMAL))

    # We are ready! Finally, we save the results
    schedule.status = status
    schedule.finished = timezone.now()
    schedule.save()
    if not status == cp_model.OPTIMAL or not status == cp_model.FEASIBLE:
        if status == cp_model.MODEL_INVALID:
            print(model.Validate())
            print(model.ModelStats())
        if status == cp_model.INFEASIBLE:
            print("Infeasible schedule")

        print(
            "Available printers: {machines_count}\nTasks: {tasks_count}\nHorizon: {horizon}"
            .format(machines_count=machines_count,
                    tasks_count=tasks_count,
                    horizon=horizon))
        # TODO : Handlear mejor el caso de que la optimizacion no tenga solucion, alivinanando constrains a cambio de una penalizacion
        return False

    for m in range(machines_count):
        # We sort task by start time
        order = lambda x: solver.Value(x.start)
        queue = [task for task in all_tasks if solver.Value(task.machine) == m]
        queue.sort(key=order)
        print("Machine {} schedule:".format(m))
        for t in queue:
            print(
                "Task {id} - copy {copy}: start {start} ends {end} with {deadline} deadline"
                .format(id=t.data.piece_id,
                        copy=t.data.copy,
                        start=round(float(solver.Value(t.start)) / 3600, 2),
                        end=round(float(solver.Value(t.end)) / 3600, 2),
                        deadline=round(float(t.data.deadline) / 3600, 2)))
    for task in all_tasks:
        o = skynet_models.ScheduleEntry.objects.create(
            schedule=schedule,
            printer=skynet_models.Printer.objects.get(
                id=machines_corresp_to_db[solver.Value(task.machine)]),
            start=relative_to_absolute_date(solver.Value(task.start)),
            end=relative_to_absolute_date(solver.Value(task.end)),
            deadline=relative_to_absolute_date(task.data.deadline))

        if 'OT' in str(task.data.piece_id):
            o.task = skynet_models.OctoprintTask.objects.get(
                id=task.data.piece_id[2:])
        else:
            o.piece = skynet_models.Piece.objects.get(id=task.data.piece_id)
        o.save()

    return schedule.id
Beispiel #23
0
def solve_flow_shop_with_ortools(filename):
    data, tasks, machines = readData(filename)
    model = cp_model.CpModel()

    max_variable_cmax = sum(task for job in data for task in job)

    # Named tuple to store information about created variables.
    task_type = collections.namedtuple('task_type', 'start end interval')
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index')

    # Creates job intervals and add to the corresponding machine lists.
    all_tasks = {}
    machine_to_intervals = collections.defaultdict(list)

    for job_id, job in enumerate(data):
        for task_id, task in enumerate(job):
            duration = task

            start_var = model.NewIntVar(
                0, max_variable_cmax,
                'start task: ' + str(job_id) + ' machine: ' + str(task_id))
            end_var = model.NewIntVar(
                0, max_variable_cmax,
                'end task: ' + str(job_id) + ' machine: ' + str(task_id))
            interval_var = model.NewIntervalVar(
                start_var, duration, end_var,
                'interval' + str(job_id) + ' machine: ' + str(task_id))
            all_tasks[job_id, task_id] = task_type(start=start_var,
                                                   end=end_var,
                                                   interval=interval_var)
            machine_to_intervals[task_id].append(interval_var)

    for machine in range(0, machines):
        model.AddNoOverlap(machine_to_intervals[machine])

    for job_id, job in enumerate(data):
        for task_id in range(0, machines - 1):
            model.Add(all_tasks[job_id, task_id +
                                1].start >= all_tasks[job_id, task_id].end)

    c_max = model.NewIntVar(0, max_variable_cmax, 'cmax-makespan')
    model.AddMaxEquality(
        c_max,
        [all_tasks[job_id, machines - 1].end for job_id in range(0, tasks)])
    model.Minimize(c_max)

    # Inicjalizujemy solver, który spróbuje znaleźć rozwiązanie w ramach naszego modelu:
    solver = cp_model.CpSolver()
    solver.parameters.max_time_in_seconds = 300.0  # dodatkowo ograniczmy czas wykonywania obliczeń do maksymalnie 5 min

    # Wszystkie ograniczenia dodane! pora odpalić solver!
    status = solver.Solve(
        model
    )  # solver zwróci status, ale jako typ wyliczeniowy, więc troche nieczytelnie dla nas

    if (
            status is not cp_model.OPTIMAL
    ):  # sprawdzamy status, aby określić czy solver znalazł rozwiązanie optymalne
        status_readable = "not optimal solution :("
    else:
        status_readable = "optimum found!"
    pi_order = []
    for task_number in range(0, tasks):
        pi_order.append(
            (task_number + 1, solver.Value(all_tasks[task_number, 0].start)))
    pi_order.sort(key=lambda x: x[1])
    pi_order = [
        x[0] for x in pi_order
    ]  # modyfikujemy naszą listę, aby przechowywać tylko numer zadań, bez czasów rozpocz

    print('C_Max: %i' % solver.ObjectiveValue())
    print("Kolejność: " + str(pi_order))
    print(status_readable)
    return solver.ObjectiveValue(), pi_order, status_readable
Beispiel #24
0
def SolveRosteringWithTravel():
    model = cp_model.CpModel()

    # [duration, start, end, location]
    jobs = [[3, 0, 6, 1], [5, 0, 6, 0], [1, 3, 7, 1], [1, 3, 5, 0],
            [3, 0, 3, 0], [3, 0, 8, 0]]

    max_length = 20

    num_machines = 3
    all_machines = range(num_machines)

    horizon = 20
    travel_time = 1
    num_jobs = len(jobs)
    all_jobs = range(num_jobs)

    intervals = []
    optional_intervals = []
    performed = []
    starts = []
    ends = []
    travels = []

    for m in all_machines:
        optional_intervals.append([])

    for i in all_jobs:
        # Create main interval.
        start = model.NewIntVar(jobs[i][1], horizon, 'start_%i' % i)
        duration = jobs[i][0]
        end = model.NewIntVar(0, jobs[i][2], 'end_%i' % i)
        interval = model.NewIntervalVar(start, duration, end,
                                        'interval_%i' % i)
        starts.append(start)
        intervals.append(interval)
        ends.append(end)

        job_performed = []
        job_travels = []
        for m in all_machines:
            performed_on_m = model.NewBoolVar('perform_%i_on_m%i' % (i, m))
            job_performed.append(performed_on_m)

            # Create an optional copy of interval to be executed on a machine
            location0 = model.NewOptionalIntVar(jobs[i][3], jobs[i][3],
                                                performed_on_m,
                                                'location_%i_on_m%i' % (i, m))
            start0 = model.NewOptionalIntVar(jobs[i][1], horizon,
                                             performed_on_m,
                                             'start_%i_on_m%i' % (i, m))
            end0 = model.NewOptionalIntVar(0, jobs[i][2], performed_on_m,
                                           'end_%i_on_m%i' % (i, m))
            interval0 = model.NewOptionalIntervalVar(
                start0, duration, end0, performed_on_m,
                'interval_%i_on_m%i' % (i, m))
            optional_intervals[m].append(interval0)

            # We only propagate the constraint if the tasks is performed on the machine.
            model.Add(start0 == start).OnlyEnforceIf(performed_on_m)
            # Adding travel constraint
            travel = model.NewBoolVar('is_travel_%i_on_m%i' % (i, m))
            startT = model.NewOptionalIntVar(0, horizon, travel,
                                             'start_%i_on_m%i' % (i, m))
            endT = model.NewOptionalIntVar(0, horizon, travel,
                                           'end_%i_on_m%i' % (i, m))
            intervalT = model.NewOptionalIntervalVar(
                startT, travel_time, endT, travel,
                'travel_interval_%i_on_m%i' % (i, m))
            optional_intervals[m].append(intervalT)
            job_travels.append(travel)

            model.Add(end0 == startT).OnlyEnforceIf(travel)

        performed.append(job_performed)
        travels.append(job_travels)

        model.Add(sum(job_performed) == 1)

    for m in all_machines:
        if m == 1:
            for i in all_jobs:
                if i == 2:
                    for c in all_jobs:
                        if (i != c) and (jobs[i][3] != jobs[c][3]):
                            is_job_earlier = model.NewBoolVar(
                                'is_j%i_earlier_j%i' % (i, c))
                            model.Add(starts[i] < starts[c]).OnlyEnforceIf(
                                is_job_earlier)
                            model.Add(starts[i] >= starts[c]).OnlyEnforceIf(
                                is_job_earlier.Not())

    # Max Length constraint (modeled as a cumulative)
    # model.AddCumulative(intervals, demands, max_length)

    # Choose which machine to perform the jobs on.
    for m in all_machines:
        model.AddNoOverlap(optional_intervals[m])

    # Objective variable.
    total_cost = model.NewIntVar(0, 1000, 'cost')
    model.Add(total_cost == sum(performed[j][m] * (10 * (m + 1))
                                for j in all_jobs for m in all_machines))
    model.Minimize(total_cost)

    # Solve model.
    solver = cp_model.CpSolver()
    result = solver.Solve(model)

    print()
    print(result)
    print('Statistics')
    print('  - conflicts       : %i' % solver.NumConflicts())
    print('  - branches        : %i' % solver.NumBranches())
    print('  - wall time       : %f ms' % solver.WallTime())
Beispiel #25
0
def main():
  # Data.
  num_nurses = 4
  num_shifts = 4     # Nurse assigned to shift 0 means not working that day.
  num_days = 7
  all_nurses = range(num_nurses)
  all_shifts = range(num_shifts)
  all_working_shifts = range(1, num_shifts)
  all_days = range(num_days)

  # Creates the model.
  model = cp_model.CpModel()

  # Creates shift variables.
  # shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
  shifts = {}
  for n in all_nurses:
    for d in all_days:
      for s in all_shifts:
        shifts[(n, d, s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))

  # Makes assignments different on each day, that is each shift is assigned at
  # most one nurse. As we have the same number of nurses and shifts, then each
  # day, each shift is assigned to exactly one nurse.
  for d in all_days:
    for s in all_shifts:
      model.Add(sum(shifts[(n, d, s)] for n in all_nurses) == 1)

  # Nurses do 1 shift per day.
  for n in all_nurses:
    for d in all_days:
      model.Add(sum(shifts[(n, d, s)] for s in all_shifts) == 1)

  # Each nurse works 5 or 6 days in a week.
  # That is each nurse works shift 0 at most 2 times.
  for n in all_nurses:
    model.AddSumConstraint([shifts[(n, d, 0)] for d in all_days], 1, 2)

  # works_shift[(n, s)] is 1 if nurse n works shift s at least one day in
  # the week.
  works_shift = {}
  for n in all_nurses:
    for s in all_shifts:
      works_shift[(n, s)] = model.NewBoolVar('works_shift_n%is%i' % (n, s))
      model.AddMaxEquality(works_shift[(n, s)],
                           [shifts[(n, d, s)] for d in all_days])

  # For each shift, at most 2 nurses are assigned to that shift during the week.
  for s in all_working_shifts:
    model.Add(sum(works_shift[(n, s)] for n in all_nurses) <= 2)

  # If a nurse works shifts 2 or 3 on, she must also work that shift the
  # previous day or the following day.
  # This means that on a given day and shift, either she does not work that
  # shift on that day, or she works that shift on the day before, or the day
  # after.
  for n in all_nurses:
    for s in [2, 3]:
      for d in all_days:
        yesterday = (d - 1) % num_days
        tomorrow = (d + 1) % num_days
        model.AddBoolOr([shifts[(n, yesterday, s)], shifts[(n, d, s)].Not(),
                         shifts[(n, tomorrow, s)]])


  # Creates the solver and solve.
  solver = cp_model.CpSolver()
  # Display a few solutions picked at random.
  a_few_solutions = [859, 2034, 5091, 7003]
  solution_printer = NursesPartialSolutionPrinter(shifts, num_nurses,
                                                  num_days, num_shifts,
                                                  a_few_solutions)
  status = solver.SearchForAllSolutions(model, solution_printer)

  # Statistics.
  print()
  print('Statistics')
  print('  - conflicts       : %i' % solver.NumConflicts())
  print('  - branches        : %i' % solver.NumBranches())
  print('  - wall time       : %f ms' % solver.WallTime())
  print('  - solutions found : %i' % solution_printer.SolutionCount())
Beispiel #26
0
def main():
    # Data
    # [START data_model]
    costs = [
        [90, 80, 75, 70],
        [35, 85, 55, 65],
        [125, 95, 90, 95],
        [45, 110, 95, 115],
        [50, 100, 90, 100],
    ]
    num_workers = len(costs)
    num_tasks = len(costs[0])
    # [END data_model]

    # Model
    # [START model]
    model = cp_model.CpModel()
    # [END model]

    # Variables
    # [START variables]
    x = []
    for i in range(num_workers):
        t = []
        for j in range(num_tasks):
            t.append(model.NewBoolVar(f'x[{i},{j}]'))
        x.append(t)
    # [END variables]

    # Constraints
    # [START constraints]
    # Each worker is assigned to at most one task.
    for i in range(num_workers):
        model.Add(sum(x[i][j] for j in range(num_tasks)) <= 1)

    # Each task is assigned to exactly one worker.
    for j in range(num_tasks):
        model.Add(sum(x[i][j] for i in range(num_workers)) == 1)
    # [END constraints]

    # Objective
    # [START objective]
    objective_terms = []
    for i in range(num_workers):
        for j in range(num_tasks):
            objective_terms.append(costs[i][j] * x[i][j])
    model.Minimize(sum(objective_terms))
    # [END objective]

    # Solve
    # [START solve]
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    # [END solve]

    # Print solution.
    # [START print_solution]
    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print(f'Total cost = {solver.ObjectiveValue()}')
        print()
        for i in range(num_workers):
            for j in range(num_tasks):
                if solver.BooleanValue(x[i][j]):
                    print(
                        f'Worker {i} assigned to task {j} Cost = {costs[i][j]}')
    else:
        print('No solution found.')
Beispiel #27
0
def main():
    """Minimal jobshop problem."""
    # Data.
    # [START data]
    jobs_data = [  # task = (machine_id, processing_time).
        [(0, 3), (1, 2), (2, 2)],  # Job0
        [(0, 2), (2, 1), (1, 4)],  # Job1
        [(1, 4), (2, 3)]  # Job2
    ]

    machines_count = 1 + max(task[0] for job in jobs_data for task in job)
    all_machines = range(machines_count)
    # Computes horizon dynamically as the sum of all durations.
    horizon = sum(task[1] for job in jobs_data for task in job)
    # [END data]

    # Create the model.
    # [START model]
    model = cp_model.CpModel()
    # [END model]

    # [START variables]
    # Named tuple to store information about created variables.
    task_type = collections.namedtuple('task_type', 'start end interval')
    # Named tuple to manipulate solution information.
    assigned_task_type = collections.namedtuple('assigned_task_type',
                                                'start job index duration')

    # Creates job intervals and add to the corresponding machine lists.
    all_tasks = {}
    machine_to_intervals = collections.defaultdict(list)

    for job_id, job in enumerate(jobs_data):
        for task_id, task in enumerate(job):
            machine = task[0]
            duration = task[1]
            suffix = '_%i_%i' % (job_id, task_id)
            start_var = model.NewIntVar(0, horizon, 'start' + suffix)
            end_var = model.NewIntVar(0, horizon, 'end' + suffix)
            interval_var = model.NewIntervalVar(start_var, duration, end_var,
                                                'interval' + suffix)
            all_tasks[job_id, task_id] = task_type(start=start_var,
                                                   end=end_var,
                                                   interval=interval_var)
            machine_to_intervals[machine].append(interval_var)
    # [END variables]

    # [START constraints]
    # Create and add disjunctive constraints.
    for machine in all_machines:
        model.AddNoOverlap(machine_to_intervals[machine])

    # Precedences inside a job.
    for job_id, job in enumerate(jobs_data):
        for task_id in range(len(job) - 1):
            model.Add(all_tasks[job_id, task_id +
                                1].start >= all_tasks[job_id, task_id].end)
    # [END constraints]

    # [START objective]
    # Makespan objective.
    obj_var = model.NewIntVar(0, horizon, 'makespan')
    model.AddMaxEquality(obj_var, [
        all_tasks[job_id, len(job) - 1].end
        for job_id, job in enumerate(jobs_data)
    ])
    model.Minimize(obj_var)
    # [END objective]

    # Creates the solver and solve.
    # [START solve]
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    # [END solve]

    # [START print_solution]
    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print('Solution:')
        # Create one list of assigned tasks per machine.
        assigned_jobs = collections.defaultdict(list)
        for job_id, job in enumerate(jobs_data):
            for task_id, task in enumerate(job):
                machine = task[0]
                assigned_jobs[machine].append(
                    assigned_task_type(start=solver.Value(
                        all_tasks[job_id, task_id].start),
                                       job=job_id,
                                       index=task_id,
                                       duration=task[1]))

        # Create per machine output lines.
        output = ''
        for machine in all_machines:
            # Sort by starting time.
            assigned_jobs[machine].sort()
            sol_line_tasks = 'Machine ' + str(machine) + ': '
            sol_line = '           '

            for assigned_task in assigned_jobs[machine]:
                name = 'job_%i_task_%i' % (assigned_task.job,
                                           assigned_task.index)
                # Add spaces to output to align columns.
                sol_line_tasks += '%-15s' % name

                start = assigned_task.start
                duration = assigned_task.duration
                sol_tmp = '[%i,%i]' % (start, start + duration)
                # Add spaces to output to align columns.
                sol_line += '%-15s' % sol_tmp

            sol_line += '\n'
            sol_line_tasks += '\n'
            output += sol_line_tasks
            output += sol_line

        # Finally print the solution found.
        print(f'Optimal Schedule Length: {solver.ObjectiveValue()}')
        print(output)
    else:
        print('No solution found.')
    # [END print_solution]

    # Statistics.
    # [START statistics]
    print('\nStatistics')
    print('  - conflicts: %i' % solver.NumConflicts())
    print('  - branches : %i' % solver.NumBranches())
    print('  - wall time: %f s' % solver.WallTime())
Beispiel #28
0
def _optimize_rule_ortools(set_opt_model_func, profile, committeesize,
                           resolute):
    """Compute ABC rules, which are given in the form of an integer optimization problem,
    using the OR-Tools CP-SAT Solver.

    Parameters
    ----------
    set_opt_model_func : callable
        sets constraints and objective and adds additional variables, see examples below for its
        signature
    profile : abcvoting.preferences.Profile
        approval sets of voters
    committeesize : int
        number of chosen alternatives
    resolute : bool

    Returns
    -------
    committees : list of sets
        a list of winning committees, each of them represented as set of integers

    """

    maxscore = None
    committees = []

    # TODO add a max iterations parameter with fancy default value which works in almost all
    #  cases to avoid endless hanging computations, e.g. when CI runs the tests
    while True:
        model = cp_model.CpModel()

        # `in_committee` is a binary variable indicating whether `cand` is in the committee
        in_committee = [
            model.NewBoolVar(f"cand{cand}_in_committee")
            for cand in profile.candidates
        ]

        set_opt_model_func(
            model,
            profile,
            in_committee,
            committeesize,
            committees,
        )

        solver = cp_model.CpSolver()
        status = solver.Solve(model)

        if status not in [cp_model.OPTIMAL, cp_model.INFEASIBLE]:
            raise RuntimeError(
                f"OR-Tools returned an unexpected status code: {status}"
                "Warning: solutions may be incomplete or not optimal.")
        elif status == cp_model.INFEASIBLE:
            if len(committees) == 0:
                # we are in the first round of searching for committees
                # and Gurobi didn't find any
                raise RuntimeError("OR-Tools found no solution (INFEASIBLE)")
            break
        objective_value = solver.ObjectiveValue()

        if maxscore is None:
            maxscore = objective_value
        elif objective_value > maxscore:
            raise RuntimeError(
                "OR-Tools found a solution better than a previous optimum. This "
                f"should not happen (previous optimal score: {maxscore}, "
                f"new optimal score: {objective_value}).")
        elif objective_value < maxscore:
            # no longer optimal
            break

        committee = set(cand for cand in profile.candidates
                        if solver.Value(in_committee[cand]) >= 1)
        if len(committee) != committeesize:
            raise RuntimeError(
                "_optimize_rule_ortools produced a committee with "
                "fewer than `committeesize` members.")
        committees.append(committee)

        if resolute:
            break

    return committees
from ortools.sat.python import cp_model

if __name__ == '__main__':
    model = cp_model.CpModel()
    solver = cp_model.CpSolver()

    #
    # decision variables
    #
    S = model.NewIntVar(0, 9, 'S')
    E = model.NewIntVar(0, 9, 'E')
    N = model.NewIntVar(0, 9, 'N')
    D = model.NewIntVar(0, 9, 'D')
    M = model.NewIntVar(0, 9, 'M')
    O = model.NewIntVar(0, 9, 'O')
    R = model.NewIntVar(0, 9, 'R')
    Y = model.NewIntVar(0, 9, 'Y')

    #
    # constraints
    #
    send = ((S * 10 + E) * 10 + N) * 10 + D
    more = ((M * 10 + O) * 10 + R) * 10 + E
    money = (((M * 10 + O) * 10 + N) * 10 + E) * 10 + Y

    model.Add(send + more == money)
    model.Add(S != 0)
    model.Add(M != 0)
    total = [S, E, N, D, M, O, R, Y]
    for i in range(len(total)):
        for j in range(i):
Beispiel #30
0
def createGrille(niveau):
    #Creates the model
    model= cp_model.CpModel()
    numVals=9
    nbrCases=0;
    if niveau=="très difficile":
        nbrCases=17
    if niveau=="difficile":
        nbrCases=26
    if niveau=="moyen":
        nbrCases=33
    if niveau=="facile":
        nbrCases=40
    if niveau=="débutant":
        nbrCases=50
    G= [[0] * 9 for i in range(9)]
    A= [[0] * 9 for i in range(9)]
    compteur=0
    #on cherche aléatoirement la position des n chiffres que l'on souhaite placés
    #leur position est modélisé par un 1
    while compteur<nbrCases :
        ligne=randint(0,8)
        colonne=randint(0,8)
        if G[ligne][colonne]==0:
            G[ligne][colonne]=1
            compteur+=1
    cellSize=3
    cell=range(cellSize)
    for ligne in range(9):
        for colonne in range(9):
            A[ligne][colonne]=model.NewIntVar(0,numVals,'A[%i][%a]' %(ligne,colonne))
               
    #contraintes
    #les éléments mis sur une ligne de peuvent pas être identiques 
    for ligne in range(9):
        diff=[]
        for colonne in range(9):
            if G[ligne][colonne]==1:
                diff.append(A[ligne][colonne])
            else:
                model.Add(A[ligne][colonne]==0) #on ne veut pas appliquer les contraintes aux 0 qui représentent des cases vides
        model.AddAllDifferent(diff)
    #aucune même valeur sur une colonne
    for colonne in range(9):
        diff=[]
        for ligne in range(9):
            if G[ligne][colonne]==1:
                diff.append(A[ligne][colonne])
        model.AddAllDifferent(diff)
       
    #aucune même valeur dans les sous-carrées de 3*3
    for i in cell:
        for j in cell:
            oneCell=[]
            for di in cell:
                for dj in cell:
                    if G[i*cellSize+di][j*cellSize+dj]==1:
                        oneCell.append(A[i*cellSize+di][j*cellSize+dj])
            model.AddAllDifferent(oneCell)   
    
    #solveur
    solver = cp_model.CpSolver()
    status = solver.Solve(model)
    if status == cp_model.FEASIBLE:
        R=[]
        for ligne in range(9):
            R.append([solver.Value(A[ligne][j]) for j in range(9)])
            print([solver.Value(A[ligne][j]) for j in range(9)])
    return R