示例#1
0
def knapsackILP(num_items, items, capacity, num_conflicts, conflicts):

    if DEBUG >= 1:
        print(f"numero de itens = {num_items}")
        print(f"capacidade da mochila = {capacity}")
        print(f"numero de conflitos = {num_conflicts}")

    if DEBUG >= 2:
        print("Itens na ordem em que foram lidos")
        for item in items:
            print(item)
        print()

    if DEBUG >= 2:
        print("Conflitos na ordem em que foram lidos")
        for conflict in conflicts:
            print(conflict)
        print()

    solution = [0] * num_items
    solution_value = 0
    solution_weight = 0

    # Começa parte PLI
    # Criação do resolvedor e das variáveis indicadoras
    solver = pywraplp.Solver('SolveIntegerProblem',
                             pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
    x = []
    for j in range(0, num_items):
        x.append(solver.IntVar(0.0, 1.0, 'x[%d]' % j))

    # Definição das restrições
    # Restrição de limite de capacidade da mochila
    solver.Add(
        sum(x[i] * items[i].weight for i in range(num_items)) <= capacity)

    # Restrição de objetos incompatíveis
    for conflict in conflicts:
        solver.Add(x[conflict[0]] + x[conflict[1]] <= 1)

    # Definição do Objetivo
    solver.Maximize(sum(x[i] * items[i].value for i in range(num_items)))

    param = pywraplp.MPSolverParameters()
    param.SetDoubleParam(param.RELATIVE_MIP_GAP, 1 / 100000)

    # Solução final
    status = solver.Solve(param)
    solution_value = int(solver.Objective().Value()
                         ) if status == pywraplp.Solver.OPTIMAL else -1
    for i in range(num_items):
        solution[i] = int(x[i].solution_value())

    # prepare the solution in the specified output format
    output_data = str(solution_value) + '\n'
    output_data += ' '.join(map(str, solution))

    return output_data
示例#2
0
def mip_ort(facilities, customers):
    solver = pywraplp.Solver.CreateSolver('SCIP')
    # solver.SetTimeLimit(15 * 60 * 1000)

    open = {}
    for facility in facilities:
        open[facility] = solver.IntVar(0, 1, '')

    dist = {}
    serves = {}
    for facility in facilities:
        serves[facility] = {}
        dist[facility] = {}
        for customer in customers:
            dist[facility][customer] = length(facility.location,
                                              customer.location)
            serves[facility][customer] = solver.IntVar(
                0, 1, '')  # if dist[facility][customer] < 50000 else 0
            # a facility can only serve if it is open
            solver.Add(serves[facility][customer] <= open[facility])

        # customer demands dont exceed capacity
        solver.Add(
            sum(serves[facility][customer] * customer.demand
                for customer in customers) <= facility.capacity)

    for customer in customers:
        # a customer is served by exactly one facility
        solver.Add(
            sum(serves[facility][customer] for facility in facilities) == 1)

    solver.Minimize(
        sum(open[facility] * facility.setup_cost +
            sum(serves[facility][customer] * dist[facility][customer]
                for customer in customers) for facility in facilities))

    solver_parameters = pywraplp.MPSolverParameters()
    solver_parameters.SetDoubleParam(
        pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.0001)

    solver.Solve(solver_parameters)

    solution = {}
    for customer in customers:
        # print("Customer", "%2d" % customer.index, ":", " ".join(map(str, map(int, (serves[facility][customer].solution_value() for facility in facilities)))))
        for facility in facilities:
            if serves[facility][customer].solution_value():
                solution[customer] = facility
                break

    print("-----Problem solved in-----")
    print('%.3f seconds' % (solver.wall_time() / 1000))
    print('%d iterations' % solver.iterations())
    print('%d branch-and-bound nodes' % solver.nodes())

    return solver.Objective().Value(), solution
示例#3
0
def get_init_subs_ort(vehicle_count, vehicle_capacity, depot, customers):
    shuffle(customers)

    in_route = {}

    solver = pywraplp.Solver.CreateSolver('SCIP')
    for customer in customers:
        for v in range(vehicle_count):
            in_route[customer, v] = solver.IntVar(0, 1, '')

        # only in one route
        solver.Add(
            sum(in_route[customer, v] for v in range(vehicle_count)) == 1)

    for v in range(vehicle_count):
        solver.Add(
            sum(in_route[customer, v] * customer.demand
                for customer in customers) <= vehicle_capacity)
    '''
    objective = 0
    for v in range(vehicle_count):
        subproblems = []
        for customer in customers:
            if in_route[customer, v]:
                subproblems.append(customer)
        objective += create_greedy_permutation(len(customers), customers)[1]

    solver.Minimize(objective)
    '''

    solver_parameters = pywraplp.MPSolverParameters()
    solver_parameters.SetDoubleParam(
        pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.0001)
    solver.Solve(solver_parameters)

    subproblems = [[] for _ in range(vehicle_count)]

    for v in range(vehicle_count):
        for customer in customers:
            if in_route[customer, v].solution_value():
                subproblems[v].append(customer)

    return subproblems
示例#4
0
    def run_model(self):
        # solver.Minimize(1)
        solver_parameters = pywraplp.MPSolverParameters()
        solver_parameters.SetDoubleParam(pywraplp.MPSolverParameters.RELATIVE_MIP_GAP, 0.5)
        self.solver.SetTimeLimit(self.solver_time_limit_mins * 60 * 1000)
        self.solver.EnableOutput()
        self.solution = self.solver.Solve()

        print('Number of variables in model = {}'.format(str(self.solver.NumVariables())))
        print('Number of constraints in model = {}'.format(str(self.solver.NumConstraints())))

        # get solution
        if self.solution == pywraplp.Solver.OPTIMAL:
            print('Solution is found')
            print('Problem solved in {} milliseconds'.format(str(self.solver.WallTime())))
            print('Problem solved in {} iterations'.format(str(self.solver.Iterations())))
            print('Problem solved in {} iterations'.format(str(self.solver.Iterations())))
            print('Problem objective = {} '.format(str(self.solver.Objective().Value())))

        else:
            raise Exception('No solution exists')
def solve_it(input_data):
    # Modify this code to run your optimization algorithm

    # parse the input
    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])

    items = []

    for i in range(1, item_count+1):
        line = lines[i]
        parts = line.split()
        items.append(Item(i-1, int(parts[0]), int(parts[1])))

    solver = pywraplp.Solver.CreateSolver('SCIP')

    taken = {}
    for item in items:
        taken[item] = solver.IntVar(0, 1, '')

    solver.Add(sum(taken[item] * item.weight for item in items) <= capacity)
    solver.Maximize(sum(taken[item] * item.value for item in items))

    # lower tolerance for better solution?
    solver_parameters = pywraplp.MPSolverParameters()
    solver_parameters.SetDoubleParam(pywraplp.MPSolverParameters.PRIMAL_TOLERANCE, 0.00001)
    solver.Solve(solver_parameters)

    solution = []

    for item in items:
        solution.append(taken[item].solution_value())
    
    # prepare the solution in the specified output format
    output_data = str(int(solver.Objective().Value())) + ' ' + str(0) + '\n'
    output_data += ' '.join(str(int(c)) for c in solution)
    return output_data
示例#6
0
    def schedule_all(self, timelimit=0):

        if not self.reservation_list:
            return self.schedule_dict

        # populate all the windows, requests, etc
        self.build_data_structures()

        # weight the priorities in each timeslice by airmass
        self.weight_by_airmass()

        # used to save a metric for when the primary algorithm fails to instantiate
        primary_algorithm_failed = 0

        # Instantiate the ORTools solver
        try:
            solver = pywraplp.Solver_CreateSolver(self.algorithm)
            if not solver:
                logger.warn(f"Failed to get a valid solver for {self.kernel}.")
                logger.warn(f"Defaulting to {FALLBACK_ALGORITHM} solver")
                primary_algorithm_failed = 1
                solver = pywraplp.Solver_CreateSolver(FALLBACK_ALGORITHM)
        except Exception as e:
            logger.warn(
                f"Failed to create a valid solver for {self.kernel}: {repr(e)}"
            )
            logger.warn(f"Defaulting to {FALLBACK_ALGORITHM} solver")
            primary_algorithm_failed = 1
            solver = pywraplp.Solver_CreateSolver(FALLBACK_ALGORITHM)

        self.send_metric('primary_algorithm_failed.occurence',
                         primary_algorithm_failed)

        # Constraint: Decision variable (isScheduled) must be binary (eq 4)
        requestLocations = []
        vars_by_req_id = defaultdict(list)
        scheduled_vars = []
        solution_hints = []
        for r in self.Yik:
            # create a lut of req_id to decision vars for building the constraints later
            # [(reqID, window idx, priority, resource, isScheduled)]
            var = solver.BoolVar(name=f"bool_var_{r[0]}_{len(scheduled_vars)}")
            scheduled_vars.append(var)
            vars_by_req_id[r[0]].append((r[0], r[1], r[2], r[3], var))
            requestLocations.append((r[0], r[1], r[2], r[3], var))
            solution_hints.append(r[4])

        # The warm-start hints (not supported in older ortools)
        if self.warm_starts:
            logger.info("Using warm start solution this run")
            solver.SetHint(variables=scheduled_vars, values=solution_hints)

        # Constraint: One-of (eq 5)
        i = 0
        for oneof in self.oneof_constraints:
            match = []
            for r in oneof:
                reqid = r.get_ID()
                match.extend(vars_by_req_id[reqid])
                r.skip_constraint2 = True  # does this do what I think it does?
            nscheduled_one = solver.Sum([
                isScheduled
                for reqid, winidx, priority, resource, isScheduled in match
            ])
            solver.Add(nscheduled_one <= 1, 'oneof_constraint_' + str(i))
            i = i + 1

        # Constraint: And (all or nothing) (eq 6)
        i = 0
        for andconstraint in self.and_constraints:
            # add decision variable that must be equal to all "and"ed blocks
            andVar = solver.BoolVar(name=f"and_var_{str(i)}")
            j = 0
            for r in andconstraint:
                reqid = r.get_ID()
                match = vars_by_req_id[reqid]
                nscheduled_and = solver.Sum([
                    isScheduled
                    for reqid, winidx, priority, resource, isScheduled in match
                ])
                solver.Add(andVar == nscheduled_and,
                           'and_constraint_' + str(i) + "_" + str(j))
                j = j + 1
            i = i + 1

        # Constraint: No more than one request should be scheduled in each (timeslice, resource) (eq 3)
        # self.aikt.keys() indexes the requests that occupy each (timeslice, resource)
        for s in sorted(self.aikt.keys()):
            match = []
            for timeslice in self.aikt[s]:
                match.append(requestLocations[timeslice])
            nscheduled1 = solver.Sum([
                isScheduled
                for reqid, winidx, priority, resource, isScheduled in match
            ])
            solver.Add(nscheduled1 <= 1, 'one_per_slice_constraint_' + s)

        # Constraint: No request should be scheduled more than once (eq 2)
        # skip if One-of (redundant)
        for r in self.reservation_list:
            if not hasattr(r, 'skip_constraint2'):
                reqid = r.get_ID()
                match = vars_by_req_id[reqid]
                nscheduled2 = solver.Sum([
                    isScheduled
                    for reqid, winidx, priority, resource, isScheduled in match
                ])
                solver.Add(nscheduled2 <= 1,
                           'one_per_reqid_constraint_' + str(reqid))

        # Objective: Maximize the merit functions of all scheduled requests (eq 1);
        objective = solver.Maximize(
            solver.Sum([
                isScheduled * (priority + (0.1 / (winidx + 1.0))) for req,
                winidx, priority, resource, isScheduled in requestLocations
            ]))

        # impose a time limit (ms) on the solve
        if timelimit > 0:
            solver.SetTimeLimit(int(timelimit * 1000))

        params = pywraplp.MPSolverParameters()
        # Set the tolerance for the model solution to be within 1% of what it thinks is the best solution
        params.SetDoubleParam(pywraplp.MPSolverParameters.RELATIVE_MIP_GAP,
                              self.mip_gap)

        # Solve the model
        solver.EnableOutput()
        solver.Solve(params)
        logger.warn("Finished solving schedule")

        # Return the optimally-scheduled windows
        r = Result()
        r.xf = []
        for request, winidx, priority, resource, isScheduled in requestLocations:
            r.xf.append(isScheduled.SolutionValue())
        logger.warn("Set SolutionValues of isScheduled")

        return self.unpack_result(r)
def formulate_and_solve_ortools_model(
        store_list, cluster_list, distance, volume,
        minimum_elements_in_a_cluster, maximum_elements_in_a_cluster,
        maximum_volume_in_a_cluster,
        enable_minimum_maximum_elements_in_a_cluster):
    '''
    Formulate the model
    :param store_list:
    :param cluster_list:
    :param distance:
    :param volume:
    :param minimum_elements_in_a_cluster:
    :param maximum_elements_in_a_cluster:
    :param maximum_volume_in_a_cluster:
    :param enable_minimum_maximum_elements_in_a_cluster:
    :return:
    '''

    # formulate model
    solver = pywraplp.Solver('SolveIntegerProblem',
                             pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)

    # create variables #
    y = {}
    for cluster, store in distance.keys():
        y[cluster, store] = solver.BoolVar('y[cluster = {}, {}]'.format(
            str(cluster), store))

    # Add constraints
    # each store is assigned to one cluster
    for store in store_list:
        solver.Add(
            solver.Sum([y[cluster, store] for cluster in cluster_list]) == 1)

    if enable_minimum_maximum_elements_in_a_cluster:
        # minimum number of elements in a cluster
        for cluster in cluster_list:
            solver.Add(
                solver.Sum([y[cluster, store] for store in store_list]) >=
                minimum_elements_in_a_cluster)

        # maximum number of elements in a cluster
        for cluster in cluster_list:
            solver.Add(
                solver.Sum([y[cluster, store] for store in store_list]) <=
                maximum_elements_in_a_cluster)
    else:

        # minimum number of elements in a cluster
        for cluster in cluster_list:
            solver.Add(
                solver.Sum([y[cluster, store] for store in store_list]) >= 1)

    if maximum_volume_in_a_cluster is not None:
        for cluster in cluster_list:
            solver.Add(
                solver.Sum([
                    volume[store] * y[cluster, store] for store in store_list
                ]) <= maximum_volume_in_a_cluster)

    # add objective
    solver.Minimize(
        solver.Sum([
            distance[cluster, store].WEIGHTED_DISTANCE * y[cluster, store]
            for cluster, store in distance.keys()
        ]))

    # solver.Minimize(1)
    solver_parameters = pywraplp.MPSolverParameters()
    solver_parameters.SetDoubleParam(
        pywraplp.MPSolverParameters.RELATIVE_MIP_GAP, 0.01)
    # solver.SetTimeLimit(self.solver_time_limit)

    solver.EnableOutput()

    solution = solver.Solve()

    # get solution
    if solution == pywraplp.Solver.OPTIMAL:

        print('Optimal solution is found')
        print('Problem solved in {} milliseconds'.format(str(
            solver.WallTime())))
        print('Problem solved in {} iterations'.format(str(
            solver.Iterations())))

        solution_final = []
        for cluster, store in distance.keys():
            solution_final.append({
                'CLUSTER':
                cluster,
                'LOCATION_NAME':
                store,
                'VALUE':
                y[cluster, store].solution_value(),
                'DISTANCE':
                distance[cluster, store].DISTANCE,
                'WEIGHTED_DISTANCE':
                distance[cluster, store].WEIGHTED_DISTANCE,
                'VOLUME':
                volume[store]
            })

        solution = pd.DataFrame(solution_final)

        solution = solution[solution['VALUE'] == 1]
        solution = solution[[
            'CLUSTER', 'LOCATION_NAME', 'DISTANCE', 'WEIGHTED_DISTANCE'
        ]]

    else:
        solution = pd.DataFrame()

    return solution
示例#8
0
def optimize(parts, listings, stores, shipping_costs):
    solver = pywraplp.Solver('lego_mip_optimization',
                             pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
    solver_params = pywraplp.MPSolverParameters()
    solver.EnableOutput()
    infinity = solver.infinity()

    vars_part_listing = []
    vars_store = []

    # Variable - part listings
    for pi in range(len(parts)):
        for li in range(len(listings)):
            if parts[pi].element_id == listings[li].element_id and parts[
                    pi].color_id == listings[li].color_id:
                var = solver.IntVar(0.0, infinity, '{}-{}'.format(pi, li))
                vars_part_listing.append(var)
            else:
                vars_part_listing.append(None)

    # Variable - stores
    for si in range(len(stores)):
        var = solver.IntVar(0.0, 1.0, 'store-{}'.format(si))
        vars_store.append(var)

    print('Number of variables', solver.NumVariables())

    # Constraint - calculate the number of stores
    for si in range(len(stores)):
        for li in range(len(listings)):
            if listings[li].store_id != stores[si].store_id:
                continue
            for pi in range(len(parts)):
                if not (parts[pi].element_id == listings[li].element_id
                        and parts[pi].color_id == listings[li].color_id):
                    continue
                index = to_var_index(parts, listings, pi, li)
                solver.Add(vars_part_listing[index] <= vars_store[si] * 10000)

    # Constraint - minimum quantity for parts
    for pi, part in enumerate(parts):
        sum = None
        for li in range(len(listings)):
            if not (parts[pi].element_id == listings[li].element_id
                    and parts[pi].color_id == listings[li].color_id):
                continue
            index = to_var_index(parts, listings, pi, li)
            if sum is None:
                sum = vars_part_listing[index]
            else:
                sum += vars_part_listing[index]
        if sum:
            solver.Add(sum >= part.qty)

    # We don't need this anymore since we decreased the number of variables
    # # Constraint - listings are associated with corresponding parts
    # for pi, part in enumerate(parts):
    #     for li, listing in enumerate(listings):
    #         if part.element_id != listing.element_id or part.color_id != listing.color_id:
    #             index = to_var_index(parts, listings, pi, li)
    #             solver.Add(vars_part_listing[index] == 0)

    # # Constraint - dont buy more than the max quantity of the vendor
    # for pi in range(len(parts)):
    #     for li, listing in enumerate(listings):
    #         if part.element_id != listing.element_id or part.color_id != listing.color_id:
    #             index = to_var_index(parts, listings, pi, li)
    #             solver.Add(vars[index] == 0)

    # # Constraint - limited number of stores
    # sum = None
    # for si in range(len(stores)):
    #     if sum is None:
    #         sum = vars_store[si]
    #     else:
    #         sum += vars_store[si]
    # solver.Add(sum <= 20)

    # Objective - minimize price
    sum = None
    for pi, part in enumerate(parts):
        for li, listing in enumerate(listings):
            if not (parts[pi].element_id == listings[li].element_id
                    and parts[pi].color_id == listings[li].color_id):
                continue
            index = to_var_index(parts, listings, pi, li)
            if not listing.price > 0:
                print('unrealistic price warning', listing.price)
            if sum is None:
                sum = vars_part_listing[index] * listing.price
            else:
                sum += vars_part_listing[index] * listing.price

    print('Number of constraints', solver.NumConstraints())

    # Objective - minimize stores
    for si in range(len(stores)):
        if sum is None:
            sum = vars_store[si] * shipping_costs
        else:
            sum += vars_store[si] * shipping_costs

    solver.Minimize(sum)

    status = solver.Solve(solver_params)

    optimal_listings = []
    if status == pywraplp.Solver.OPTIMAL:
        for pi in range(len(parts)):
            sys.stdout.write('{}'.format(parts[pi]))
            for li in range(len(listings)):
                if parts[pi].element_id == listings[li].element_id and parts[
                        pi].color_id == listings[li].color_id:
                    solution = vars_part_listing[to_var_index(
                        parts, listings, pi, li)].solution_value()
                    if solution > 0:
                        sys.stdout.write(' {}'.format(listings[li]))
                        optimal_listings.append(listings[li])
            print('')
        # for si in range(len(stores)):
        #     print(stores[si].store_id, vars_store[si].solution_value())
        print('Solution:')
        print('Objective value =', solver.Objective().Value())
    else:
        print('The problem does not have an optimal solution.')

    return optimal_listings