Пример #1
0
def find_transform(x, y, limit, threshold=1e-7):
    """
    find a integer solution to ax + b - cxy - dy = 0
    this will give us the mobius transform: T(x) = y
    :param x: numeric constant to check
    :param y: numeric manipulation of constant
    :param limit: range to look at
    :param threshold: optimal solution threshold.
    :return MobiusTransform in case of success or None.
    """
    x1 = x
    x2 = dec(1.0)
    x3 = -x * y
    x4 = -y
    solver = Solver('mobius', Solver.CBC_MIXED_INTEGER_PROGRAMMING)
    a = solver.IntVar(-limit, limit, 'a')
    b = solver.IntVar(-limit, limit, 'b')
    c = solver.IntVar(-limit, limit, 'c')
    d = solver.IntVar(-limit, limit, 'd')
    f = solver.NumVar(0, 1, 'f')
    solver.Add(f == (a * x1 + b * x2 + c * x3 + d * x4))
    solver.Add(a * x1 + b >=
               1)  # don't except trivial solutions and remove some redundancy
    solver.Minimize(f)
    status = solver.Solve()
    if status == Solver.OPTIMAL:
        if abs(solver.Objective().Value()) <= threshold:
            res_a, res_b, res_c, res_d = int(a.solution_value()), int(b.solution_value()),\
                                         int(c.solution_value()), int(d.solution_value())
            ret = MobiusTransform(
                np.array([[res_a, res_b], [res_c, res_d]], dtype=object))
            ret.normalize()
            return ret
    else:
        return None
Пример #2
0
    def _solve_optimization(self, solver: pywraplp.Solver) -> None:
        # The MIP solver is usually fast (milliseconds). If we hit a weird problem,
        # accept a suboptimal solution after 10 seconds.
        solver.SetTimeLimit(10000)
        status = solver.Solve()

        if status == pywraplp.Solver.INFEASIBLE:
            raise Exception("Infeasible problem")
        elif status == pywraplp.Solver.NOT_SOLVED:
            raise Exception("Problem unsolved")
Пример #3
0
def _attempt_to_improve_var_bounds_one_hs(solver: pywraplp.Solver,
                                          coefficient_part: str, is_leq: bool,
                                          right_hand_side: str):
    coefficient_part = coefficient_part.strip()
    if re.match(_REGEXP_SINGLE_VAR_NAME_ALL, coefficient_part):
        if is_leq:
            solver.LookupVariable(coefficient_part).SetUb(
                float(right_hand_side))
        else:
            solver.LookupVariable(coefficient_part).SetLb(
                float(right_hand_side))
Пример #4
0
def main():
    # Create the linear solver with the GLOP backend.
    solver = Solver('simple_lp_program', Solver.GLOP_LINEAR_PROGRAMMING)

    # Create the variables x and y.
    x = solver.NumVar(0, 1, 'x')
    y = solver.NumVar(0, 2, 'y')

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

    # Create a linear constraint, 0 <= x + y <= 2.
    ct = solver.Constraint(0, 2, 'ct')
    ct.SetCoefficient(x, 1)
    ct.SetCoefficient(y, 1)

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

    # Create the objective function, 3 * x + y.
    objective = solver.Objective()
    objective.SetCoefficient(x, 3)
    objective.SetCoefficient(y, 1)
    objective.SetMaximization()

    solver.Solve()

    print('Solution:')
    print('Objective value =', objective.Value())
    print('x =', x.solution_value())
    print('y =', y.solution_value())
Пример #5
0
    def _solve_optimization(self, solver: pywraplp.Solver) -> bool:
        # The MIP solver is usually fast (milliseconds). If we hit a weird problem,
        # accept a suboptimal solution after 10 seconds.
        solver.SetTimeLimit(10000)
        status = solver.Solve()

        if status == pywraplp.Solver.INFEASIBLE:
            logger.warning("Optimization problem is infeasible")
            return False
        elif status == pywraplp.Solver.NOT_SOLVED:
            logger.warning("Optimization problem could not be solved in time")
            return False

        return True
Пример #6
0
def solve_problem() -> None:
    solver: Solver = Solver("simple_mip_program",
                            Solver.CBC_MIXED_INTEGER_PROGRAMMING)

    x: Any = solver.IntVar(0, 100, "x")
    y: Any = solver.IntVar(0, 100, "y")

    solver.Add(1 * x + 2 * y <= 40)
    solver.Add(4 * x + 4 * y <= 80)
    solver.Add(3 * x + 1 * y <= 50)

    solver.Maximize(x * 5.0 + y * 4.0)

    status: Any = solver.Solve()

    if status == Solver.OPTIMAL or status == Solver.FEASIBLE:
        print("Solution: OK")
        print("Objective value =", solver.Objective().Value())

        if x.solution_value() > 0.5:
            print("x =", x.solution_value())
            print("y =", y.solution_value())
        print("Time = ", solver.WallTime(), " milliseconds")
    else:
        print("The problem does not have an optimal solution.")
Пример #7
0
def _parse_objective_function(solver: pywraplp.Solver, core_line: str,
                              line_nr: int, var_names: set):
    spl_colon = core_line.split(":", maxsplit=1)

    objective = solver.Objective()

    # Set maximization / minimization if specified
    if len(spl_colon) == 1:
        raise ValueError(
            "Objective function on line %d must start with \"max:\" or \"min:\"."
            % line_nr)
    else:
        if spl_colon[0] != "max" and spl_colon[0] != "min":
            raise ValueError(
                "Objective function on line %d must start with \"max:\" or \"min:\"."
                % line_nr)
        elif spl_colon[0] == "max":
            objective.SetMaximization()
        else:
            objective.SetMinimization()

        # Set the remainder
        coefficient_part = spl_colon[1].strip()

        # Finally set the coefficients of the objective
        constant = _set_coefficients(solver, objective, coefficient_part,
                                     line_nr, var_names)
        objective.SetOffset(constant)
Пример #8
0
    def _declare_constraint(
        solver: pywraplp.Solver,
        group: "Group",
        variables: typing.Tuple[typing.Tuple[pywraplp.Variable]],
    ) -> None:
        higher_groups = group.get_simultaneous_groups_of_higher_cycle()
        if higher_groups:
            # fixed duration of group
            summed_active_transitions_of_group = Group._sum_active_transitions_of_group(
                group, higher_groups)

            # fixed duration of higher groups
            summed_transitions_of_higher_groups = sum(
                Group._calculate_duration_of_n_phases(higher_group,
                                                      higher_group.attack)
                for higher_group in higher_groups)
            summed_transitions_of_higher_groups += Group._calculate_duration_of_n_phases(
                higher_groups[-1], higher_groups[-1].release)
            difference_of_duration = (summed_active_transitions_of_group -
                                      summed_transitions_of_higher_groups)
            constraint = sum(
                Group._calculate_duration_of_n_phases(higher_group, var)
                for var, higher_group in zip(variables[1], higher_groups))
            constraint = constraint - (Group._calculate_duration_of_n_phases(
                group, variables[0][0]))
            solver.Add(constraint == difference_of_duration)
Пример #9
0
 def _declare_variable(self, solver: pywraplp.Solver, nth_cycle: int,
                       nth_index: int) -> None:
     return solver.NumVar(
         MIN_N_PHASES_FOR_SUSTAIN,
         MIN_N_PHASES_FOR_SUSTAIN * MAX_N_MIN_PHASES_FOR_SUSTAIN,
         self._get_variable_name(nth_cycle, nth_index),
     )
Пример #10
0
def solve_problem() -> None:
    solver: Solver = Solver("simple_mip_program",
                            Solver.CBC_MIXED_INTEGER_PROGRAMMING)

    backet: Dict = {j: solver.BoolVar(f"x{j}") for j in range(5)}

    solver.Add(
        solver.Sum(list(VOLUMES[j] * backet[j]
                        for j in range(len(VOLUMES)))) <= CAPASITY)

    solver.Maximize(
        solver.Sum(list(VALUES[j] * backet[j] for j in range(len(VOLUMES)))))

    status: Any = solver.Solve()

    if status == Solver.OPTIMAL or status == Solver.FEASIBLE:
        print("Solution: OK")
        print("Objective value =", solver.Objective().Value())
        print("culculate Time = ", solver.WallTime(), " milliseconds")

        print("select item")
        for j in range(len(VOLUMES)):
            print(j, backet[j].solution_value())

        print("total value")
        print(
            sum(VALUES[j] * backet[j].solution_value()
                for j in range(len(VOLUMES))))

    else:
        print("The problem does not have an optimal solution.")
Пример #11
0
    def _add_stock_variables(num_types: int, num_time_periods: int, solver: Solver) \
            -> Dict[V, Variable]:
        """Create stock variables.

         A stock variable $s^t_p$ is a non-negative real variable which represents the number of
         items of type $t$ on stock in time period $p$.

        :param num_types: the number of considered types
        :param num_time_periods: the number of considered time periods
        :param solver: the underlying solver for which to built the variables
        :return: A dictionary mapping each stock variable to its solver variable
        """
        stock_vars = dict()
        for (item_type, time_period) in product(range(num_types),
                                                range(-1, num_time_periods)):
            stock_vars[V(type=item_type, period=time_period)] = \
                solver.NumVar(lb=0., ub=solver.infinity(), name=f's_{item_type}_{time_period}')
        module_logger.info(f'Created {len(stock_vars)} stock variables.')
        return stock_vars
Пример #12
0
 def __init__(self, prob_input: Input, solver_id: str, solver_output: bool):
     self.prob_input = prob_input
     self.solver_id = solver_id
     self.solver = Solver.CreateSolver(solver_id)
     self.production_vars = None
     self.configuration_vars = None
     self.stock_vars = None
     self.transition_vars = None
     self.pred_configuration_vars = None
     self.succ_configuration_vars = None
     if solver_output:
         self.solver.EnableOutput()
     else:
         self.solver.SuppressOutput()
Пример #13
0
def _parse_declaration(solver: pywraplp.Solver, core_line: str, line_nr: int,
                       var_names: set):
    spl_whitespace = core_line.split(maxsplit=1)

    if spl_whitespace[0] != "int":
        raise ValueError("Declaration on line %d should start with \"int \"." %
                         line_nr)

    if len(spl_whitespace) != 2:
        raise ValueError("Declaration on line %d has no variables." % line_nr)

    spl_variables = spl_whitespace[1].split(",")
    for raw_var in spl_variables:
        clean_var = raw_var.strip()
        if not re.match(_REGEXP_SINGLE_VAR_NAME_ALL, clean_var):
            raise ValueError(
                "Non-permitted variable name (\"%s\") on line %d." %
                (clean_var, line_nr))
        if clean_var in var_names:
            raise ValueError("Variable \"%s\" declared again on line %d." %
                             (clean_var, line_nr))
        var_names.add(clean_var)
        solver.IntVar(-solver.infinity(), solver.infinity(), clean_var)
Пример #14
0
def cap_mip(customers, facilities, max_time=60):
    n_fac = len(facilities)
    n_cust = len(customers)
    solver = Solver.CreateSolver("FacilityLocation", "SCIP")

    x = []
    y = []
    for f in range(n_fac):
        y.append([solver.BoolVar(f"y_{f}_{c}") for c in range(n_cust)])
        x.append(solver.BoolVar(f"x_{f}"))

    caps = [f.capacity for f in facilities]
    setup = [f.setup_cost for f in facilities]
    dist = distance_matrix(customers, facilities).astype(int)
    demands = [c.demand for c in customers]

    for f in range(n_fac):
        for c in range(n_cust):
            solver.Add(y[f][c] <= x[f])
    for c in range(n_cust):
        solver.Add(sum([y[f][c] for f in range(n_fac)]) == 1)
    for f in range(n_fac):
        solver.Add(sum([y[f][c] * demands[c] for c in range(n_cust)]) <= caps[f])

    obj = 0
    for f in range(n_fac):
        obj += setup[f] * x[f]
        obj += sum([dist[f][c] * y[f][c] for c in range(n_cust)])

    solver.Minimize(obj)

    STATUS = {
        Solver.FEASIBLE: "FEASIBLE",
        Solver.UNBOUNDED: "UNBOUNDED",
        Solver.BASIC: "BASIC",
        Solver.INFEASIBLE: "INFEASIBLE",
        Solver.NOT_SOLVED: "NOT_SOLVED",
        Solver.OPTIMAL: "OPTIMAL",
    }
    solver.SetTimeLimit(max_time * 1000)

    status = solver.Solve()
    STATUS[status]
    a = []
    for f in range(n_fac):
        a.append([y[f][c].solution_value() for c in range(n_cust)])

    sol = np.array(a).argmax(axis=0)
    return sol, STATUS[status]
Пример #15
0
    def _add_production_variables(num_types: int, num_time_periods: int,
                                  solver: Solver) -> Dict[V, Variable]:
        """Create production variables.

        A production variable $x^t_p$ is a binary variable which is one if and only if an item of
        type $t$ is produced in time period $p$.

        :param num_types: the number of considered types
        :param num_time_periods: the number of considered time periods
        :param solver: the underlying solver for which to built the variables
        :return: A dictionary mapping each production variable to its solver variable
        """
        production_vars = dict()
        for (item_type, time_period) in product(range(num_types),
                                                range(num_time_periods)):
            production_vars[V(type=item_type,
                              period=time_period)] = solver.BoolVar(
                                  name=f'x_{item_type}_{time_period}')
        module_logger.info(
            f'Created {len(production_vars)} production variables.')
        return production_vars
Пример #16
0
    def _add_configuration_variables(num_types: int, num_time_periods: int, solver: Solver) \
            -> Dict[V, Variable]:
        """Create configuration variables.

        A configuration variable $y^t_p$ is a binary variable which is one if and only if the
        machine is configured for type $t$ in time period $p$.

        :param num_types: the number of considered types
        :param num_time_periods: the number of considered time periods
        :param solver: the underlying solver for which to built the variables
        :return: A dictionary mapping each configuration tuple to its solver variable

        """
        configuration_vars = dict()
        for (item_type, time_period) in product(range(num_types),
                                                range(num_time_periods)):
            configuration_vars[V(type=item_type,
                                 period=time_period)] = solver.BoolVar(
                                     name=f'y_{item_type}_{time_period}')
        module_logger.info(
            f'Created {len(configuration_vars)} configuration variables.')
        return configuration_vars
def solve_problem() -> None:
    solver: Solver = Solver("simple_mip_program",
                            Solver.CBC_MIXED_INTEGER_PROGRAMMING)

    amount: Dict = {}
    for i in range(3):
        for j in range(4):
            amount[i, j] = solver.IntVar(0, 50, f"val{i}_{j}")

    amount_w1, amount_w2, amount_w3 = get_quantity_carried_out(amount)
    solver.Add(amount_w1 <= 35)
    solver.Add(amount_w2 <= 41)
    solver.Add(amount_w3 <= 42)

    amount_f1, amount_f2, amount_f3, amount_f4 = get_quantity_carried_in(
        amount)
    solver.Add(amount_f1 >= 28)
    solver.Add(amount_f2 >= 29)
    solver.Add(amount_f3 >= 31)
    solver.Add(amount_f4 >= 25)

    solver.Minimize(
        solver.Sum(
            [amount[i, j] * COST[i][j] for i in range(3) for j in range(4)]))

    status: Any = solver.Solve()

    if status == Solver.OPTIMAL or status == Solver.FEASIBLE:
        print("Solution: OK")
        print("Objective value =", solver.Objective().Value())
        print("=============================================")
        for i in range(3):
            for j in range(4):
                if amount[i, j].SolutionValue() > 0:
                    print(i, j, amount[i, j].SolutionValue())
        print("Time = ", solver.WallTime(), " milliseconds")
    else:
        print("The problem does not have an optimal solution.")
Пример #18
0
    def _add_transition_variables(num_types: int, num_time_periods: int, solver: Solver) \
            -> Dict[W, Variable]:
        """Create transition variables.

        A transition variable $u^ij_p$ is a binary variable which is one if and only if the
        machine's configuration changes from type $i$ to type $j$ in time period $p$.

        :param num_types: the number of considered types
        :param num_time_periods: the number of considered time periods
        :param solver: the underlying solver for which to built the variables
        :return: A dictionary mapping each transition variable to its solver variable
        """
        transition_vars = dict()
        for type_i, type_j, time_period in product(range(num_types),
                                                   range(num_types),
                                                   range(1, num_time_periods)):
            transition_vars[W(from_type=type_i,
                              to_type=type_j,
                              from_period=time_period - 1,
                              to_period=time_period)] = solver.BoolVar(
                                  name=f'u_{type_i}_{type_j}_{time_period}')
        module_logger.info(
            f'Created {len(transition_vars)} transition variables.')
        return transition_vars
Пример #19
0
def cap_mip2(customers,
             facilities,
             max_time=60,
             min_fac=None,
             max_fac=None,
             k_neigh=None):
    n_fac = len(facilities)
    n_cust = len(customers)
    solver = Solver.CreateSolver("FacilityLocation", "SCIP")
    if min_fac is None:
        min_fac = min_facilities(customers, facilities)
    print(f'Minimum Facilities: {min_fac}')
    est_fac = est_facilities(customers, facilities)
    est_fac = max(5, min_fac)
    print('Estimated Facilities:', est_fac)
    if k_neigh is None:
        k_neigh = n_fac // est_fac * 2
        k_neigh = min(k_neigh, n_fac // 2)
    print(f'Only using {k_neigh} nearest facilities')

    # Estimate Customers per Facilitiy
    cpf = n_cust // min_fac
    cpf = np.clip(cpf, 2, n_cust // 2)

    # Define Variables
    x = []
    y = []
    for f in range(n_fac):
        y.append([solver.BoolVar(f"y_{f}_{c}") for c in range(n_cust)])
        x.append(solver.BoolVar(f"x_{f}"))

    caps = np.array([f.capacity for f in facilities])
    setup = np.array([f.setup_cost * 100 for f in facilities])
    dist = distance_matrix(customers, facilities) * 100
    dist = dist.astype(int)
    demands = np.array([c.demand for c in customers])

    # Problem Analysis
    free_setup = np.where(caps == 0)[0]
    is_fixed_setup = True if np.std(caps[caps > 0]) == 0 else False

    # Add Constraints
    print('\t Adding Constaints')
    # If facility is closed then it is not connected to any customer
    for f in range(n_fac):
        for c in range(n_cust):
            solver.Add(y[f][c] <= x[f])

    # Each customer is connected to only one facility
    for c in range(n_cust):
        solver.Add(sum([y[f][c] for f in range(n_fac)]) == 1)

    # The demand is not more than the capacity of the facility
    for f in range(n_fac):
        solver.Add(
            sum([y[f][c] * demands[c]
                 for c in range(n_cust)]) <= caps[f] * x[f])
        solver.Add(
            sum([y[f][c] * demands[c] for c in range(n_cust)]) <= caps[f])

    # Customers per facility
    for f in range(n_fac):
        solver.Add(sum([y[f][c] for c in range(n_cust)]) <= n_cust * x[f])

    # The free facilities must be open
    for f in free_setup:
        solver.Add(x[f] == 1)

    # Customer can ONLY connect to nearby facilities
    for c in range(n_cust):
        idx = np.argsort(dist[:, c])
        for f in idx[k_neigh:]:
            solver.Add(y[f][c] == 0)

    print('\t Adding Covercut Constaints')
    # Cover cut for customers which can be connected to a facility
    #     round1 = []
    #     round2 = []
    #     for f in range(n_fac):
    #         argsort = np.argsort(dist[f, :])
    #         idx = argsort[:cpf]
    #         if sum(demands[idx]) > caps[f]:
    #             round1.append(f)
    #             solver.Add(sum([y[f][c] for c in idx]) <= (cpf - 1))
    #         if cpf > 4:
    #             k = int(cpf * .9)
    #             idx = argsort[:k]
    #             if sum(demands[idx]) > caps[f]:
    #                 round2.append(f)
    #                 solver.Add(sum([y[f][c] for c in idx]) <= (k - 1))

    #     print(round1)
    #     print(round2, flush=True)

    # Maximum Facility open
    solver.Add(sum(x) >= min_fac)
    if max_fac is not None:
        solver.Add(sum(x) <= max_fac)
    #     solver.Add(sum(x)>=2)

    # Define objective
    obj = 0
    for f in range(n_fac):
        # Setup cost
        if not is_fixed_setup:
            obj += setup[f] * x[f]
        # Service cost
        obj += sum([dist[f][c] * y[f][c] for c in range(n_cust)])
    solver.Minimize(obj)

    STATUS = {
        Solver.FEASIBLE: "FEASIBLE",
        Solver.UNBOUNDED: "UNBOUNDED",
        Solver.BASIC: "BASIC",
        Solver.INFEASIBLE: "INFEASIBLE",
        Solver.NOT_SOLVED: "NOT_SOLVED",
        Solver.OPTIMAL: "OPTIMAL",
    }
    solver.SetTimeLimit(max_time * 1000)

    # Solve
    print('\t Starting the Solver')
    status = solver.Solve()
    STATUS[status]

    # Retreive values
    a = []
    for f in range(n_fac):
        a.append([y[f][c].solution_value() for c in range(n_cust)])

    # Convert solution matrix to facility index
    sol = np.array(a).argmax(axis=0)

    return sol, STATUS[status]
Пример #20
0
#!/bin/python

from ortools.linear_solver import pywraplp
from ortools.linear_solver.pywraplp import Solver

# A person needs three nutrients. Let's assume they are vitamins A, B and C.
Nutrition = [2000, 300, 430]
# They can be supplied by four foods. The first number if the calories supplied
# by a food type. The remaining three numbers are the nutrients.
Foods = [['Trout', 600, 203, 92, 100], ['CB Sandwich', 350, 90, 84, 230],
         ['Burrito', 250, 270, 80, 512], ['Hamburger', 500, 500, 90, 210]]
# A person needs a certain minimum calories.
MinCalories = 2500

solver = Solver.CreateSolver('diet', 'CBC')
# The decision variables. How much quantity of each food typu should a person
# consume?
consumption = [None] * len(Foods)
for i in range(0, len(Foods)):
    consumption[i] = solver.IntVar(1, solver.infinity(), Foods[i][0])

# The objective function is to minimize the number of calories.
objf = solver.Objective()
for i in range(0, len(Foods)):
    objf.SetCoefficient(consumption[i], Foods[i][1])

objf.SetMinimization()

# Add constraints. Unlike the previous examples where we had our constraints
# given to us as inequalities, here we will have to build them from the given
# data.
Пример #21
0
 def _compute_compact_linearisation_sets(self, *, z_weight: float, f_weight: float) \
         -> Tuple[Dict[int, List[V]], List[Tuple[V, V]]]:
     """Computes sets F and B_k used in Liberti's compact formulation."""
     _solver = Solver.CreateSolver(self.solver_id)
     f_vars = dict()
     z_vars = dict()
     N = bidict()
     for time_period in range(self.prob_input.num_time_periods):
         for item_type in range(self.prob_input.num_types):
             N[V(type=item_type, period=time_period)] = 1 + len(N)
     M = lambda i: (j for j in N.values() if i <= j)
     K = list(range(self.prob_input.num_time_periods))
     # create f_ij \in [0,1] for all 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             f_vars[(i, j)] = _solver.NumVar(lb=0.,
                                             ub=1.,
                                             name=f'f_{str(i)}{str(j)}')
     # create z_ik \in {0,1} for all k \in K, 1 <= i <= n
     for k in K:
         for i in N.values():
             z_vars[(i, k)] = _solver.BoolVar(name=f'z_{str(i)}{str(k)}')
     # add constraints: f_ij = 1 \forall (i,j) \in E
     for var in self.transition_vars.keys():
         i = N[V(type=var.from_type, period=var.from_period)]
         j = N[V(type=var.to_type, period=var.to_period)]
         _solver.Add(f_vars[(i, j)] == 1, name='cons_10')
     # add constraints: f_ij >= z_jk \forall k \in K, i \in A_k, j \in N, i <= j
     for k in K:
         A_k = [
             N[V(type=item_type, period=k)]
             for item_type in range(self.prob_input.num_types)
         ]
         for i in A_k:
             for j in M(i):
                 lhs = f_vars[(i, j)]
                 rhs = z_vars[(j, k)]
                 _solver.Add(lhs >= rhs, name='cons_11')
     # add constraints: f_ji >= z_jk \forall k \in K, i \in A_k, j \ín N, j < i
     for k in K:
         A_k = [
             N[V(type=item_type, period=k)]
             for item_type in range(self.prob_input.num_types)
         ]
         for i in A_k:
             for j in (j for j in N.values() if j < i):
                 lhs = f_vars[(j, i)]
                 rhs = z_vars[(j, k)]
                 _solver.Add(lhs >= rhs, name='cons_12')
     # add constraints: \sum_{k: i \in A_k} z_jk >= f_ij \forall 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             k = N.inverse[i].period
             lhs = z_vars[(j, k)]
             rhs = f_vars[(i, j)]
             _solver.Add(lhs >= rhs, name='cons_13')
     # add constraints: \sum_{k: j \in A_k} z_ik >= f_ij \forall 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             k = N.inverse[j].period
             lhs = z_vars[(i, k)]
             rhs = f_vars[(i, j)]
             _solver.Add(lhs >= rhs, name='cons_14')
     # add objective
     z_obj = _solver.Sum(z_weight * var for var in z_vars.values())
     f_obj = _solver.Sum(f_weight * var for var in f_vars.values())
     _solver.Minimize(z_obj + f_obj)
     # solve
     status = _solver.Solve()
     if status == Solver.OPTIMAL:
         B = defaultdict(list)
         for i, k in (key for key, var in z_vars.items()
                      if var.solution_value() > 0.99):
             B[k].append(N.inverse[i])
         F = [(N.inverse[i], N.inverse[j])
              for (i, j), var in f_vars.items()
              if var.solution_value() > 0.99]
         return B, F
     else:
         raise RuntimeError('No optimal solution found.')
Пример #22
0
# certain number of items.
#
# Suppose that we are given items of a certain weight. They should be 
# transported through wagons of a certain capacity. What is the least number
# of wagons that we should hire to carry all goods?

itemWts = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30]
maxwt = 100

# We ensure that every item can be fitted in a wagon. That is, none of them
# has a weight more than the wagon's capacity.

from ortools.linear_solver import pywraplp
from ortools.linear_solver.pywraplp import Solver

solver = Solver.CreateSolver('bin-packing', 'CBC')

# The decision variables are of the form x_{ij}. They take a value 1 if
# item i is put in wagon j, 0 otherwise.
nItems = len(itemWts)
nWagons = nItems

x = {}
for i in range(0, nItems):
    for j in range(0, nWagons):
        vname = f'x[{i}, {j}]'
        x[(i, j)] = solver.IntVar(0, 1, vname)

# Recall that we need at most as many wagons as we have items. w[i] is 1
# is wagon i is used.
w = [None] * nWagons
Пример #23
0
# The data.
nResources = 7
nItems = 12
resourceAvailability = [18209, 7692, 1333, 924, 26638, 61188, 13360]
itemValue = [96, 76, 56, 11, 86, 10, 66, 86, 83, 12, 9, 81]
resourceUse = [
      [19,   1,  10,  1,   1,  14, 152, 11,  1,   1, 1, 1],
      [ 0,   4,  53,  0,   0,  80,   0,  4,  5,   0, 0, 0],
      [ 4, 660,   3,  0,  30,   0,   3,  0,  4,  90, 0, 0],
      [ 7,   0,  18,  6, 770, 330,   7,  0,  0,   6, 0, 0],
      [ 0,  20,   0,  4,  52,   3,   0,  0,  0,   5, 4, 0],
      [ 0,   0,  40, 70,   4,  63,   0,  0, 60,   0, 4, 0],
      [ 0,  32,   0,  0,   0,   5,   0,  3,  0, 660, 0, 9]]

solver = Solver.CreateSolver('multi-knapsack', 'CBC')

# How many numbers of each items should be packed? Each one of these is a 
# decision variable.
take = [None] * nItems
for i in range(0, nItems):
    take[i] = solver.IntVar(0, solver.infinity(), f'take[{i}]')

# Build the objective function.
objf = solver.Objective()
for i in range(0, nItems):
    objf.SetCoefficient(take[i], itemValue[i])

objf.SetMaximization()

for i in range(0, nResources):
Пример #24
0
        [5, 7, 9, 2, 1],
        [18, 4, -9, 10, 12],
        [4, 7, 3, 8, 5],
        [5, 13, 16, 3, -7],
    ]
    data['bounds'] = [250, 285, 211, 315]
    data['obj_coeffs'] = [7, 8, 2, 9, 6]
    data['num_vars'] = 5
    data['num_constraints'] = 4

    return data


data = create_data_model()

solver = Solver.CreateSolver('mip', 'CBC')
# Quite like in the case of the 'Diet problem' the decision variables are
# created as elements of a list.
x = [None] * data['num_vars']
for i in range(0, len(x)):
    x[i] = solver.IntVar(0, solver.infinity(), f'x[{i}]')

print(f'Number of variables = {solver.NumVariables()}')

# Build the constraints.
for i in range(0, data['num_constraints']):
    cn = solver.Constraint(0, data['bounds'][i], f'cn[{i}]')
    for j in range(0, data['num_vars']):
        cn.SetCoefficient(x[j], data['constraint_coeffs'][i][j])
print(f'Number of constraints = {solver.NumConstraints()}')
Пример #25
0
def _parse_constraint(solver: pywraplp.Solver, core_line: str, line_nr: int,
                      var_names: set):

    # We don't care about the coefficient name before the colon
    constraint_part = core_line
    spl_colon = core_line.split(":", maxsplit=1)
    if len(spl_colon) > 1:
        constraint_part = spl_colon[1].strip()

    # Equality constraint
    if constraint_part.find("=") >= 0 and constraint_part.find(
            "<=") == -1 and constraint_part.find(">=") == -1:
        equality_spl = constraint_part.split("=")
        if len(equality_spl) > 2:
            raise ValueError(
                "Equality constraint on line %d has multiple equal signs." %
                line_nr)
        if not _is_valid_constant_float(equality_spl[1]):
            raise ValueError(
                "Right hand side (\"%s\") of equality constraint on line %d is not a float "
                "(e.g., variables are not allowed there!)." %
                (equality_spl[1], line_nr))
        equal_value = float(equality_spl[1])
        constraint = solver.Constraint(equal_value, equal_value)
        constant = _set_coefficients(solver, constraint, equality_spl[0],
                                     line_nr, var_names)
        constraint.SetLb(constraint.Lb() - constant)
        constraint.SetUb(constraint.Ub() - constant)
        _attempt_to_improve_var_bounds_two_hs(solver, equality_spl[0], True,
                                              equality_spl[1], equality_spl[1])

    # Inequality constraints
    else:

        # Replace all of these inequality signs, because they are equivalent
        constraint_part = constraint_part.replace("<=", "<").replace(">=", ">")

        # lower bound < ... < upper bound
        if constraint_part.count("<") == 2:
            spl = constraint_part.split("<")
            if not _is_valid_constant_float(spl[0]):
                raise ValueError(
                    "Left hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[0], line_nr))
            if not _is_valid_constant_float(spl[2]):
                raise ValueError(
                    "Right hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[2], line_nr))
            constraint = solver.Constraint(float(spl[0]), float(spl[2]))
            constant = _set_coefficients(solver, constraint, spl[1], line_nr,
                                         var_names)
            constraint.SetLb(constraint.Lb() - constant)
            constraint.SetUb(constraint.Ub() - constant)
            _attempt_to_improve_var_bounds_two_hs(solver, spl[1], True, spl[0],
                                                  spl[2])

        # upper bound > ... > lower bound
        elif constraint_part.count(">") == 2:
            spl = constraint_part.split(">")
            if not _is_valid_constant_float(spl[0]):
                raise ValueError(
                    "Left hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[0], line_nr))
            if not _is_valid_constant_float(spl[2]):
                raise ValueError(
                    "Right hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[2], line_nr))
            constraint = solver.Constraint(float(spl[2]), float(spl[0]))
            constant = _set_coefficients(solver, constraint, spl[1], line_nr,
                                         var_names)
            constraint.SetLb(constraint.Lb() - constant)
            constraint.SetUb(constraint.Ub() - constant)
            _attempt_to_improve_var_bounds_two_hs(solver, spl[1], False,
                                                  spl[0], spl[2])

        # ... < upper bound
        elif constraint_part.count("<") == 1:
            spl = constraint_part.split("<")
            if not _is_valid_constant_float(spl[1]):
                raise ValueError(
                    "Right hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[1], line_nr))
            constraint = solver.Constraint(-solver.infinity(), float(spl[1]))
            constant = _set_coefficients(solver, constraint, spl[0], line_nr,
                                         var_names)
            constraint.SetUb(constraint.Ub() - constant)
            _attempt_to_improve_var_bounds_one_hs(solver, spl[0], True, spl[1])

        # ... > lower bound
        elif constraint_part.count(">") == 1:
            spl = constraint_part.split(">")
            if not _is_valid_constant_float(spl[1]):
                raise ValueError(
                    "Right hand side (\"%s\") of inequality constraint on line %d is not a float "
                    "(e.g., variables are not allowed there!)." %
                    (spl[1], line_nr))
            constraint = solver.Constraint(float(spl[1]), solver.infinity())
            constant = _set_coefficients(solver, constraint, spl[0], line_nr,
                                         var_names)
            constraint.SetLb(constraint.Lb() - constant)
            _attempt_to_improve_var_bounds_one_hs(solver, spl[0], False,
                                                  spl[1])

        # ...
        elif constraint_part.count(">") == 0 and constraint_part.count(
                "<") == 0:
            raise ValueError(
                "No (in)equality sign present for constraint on line %d." %
                line_nr)

        # Some strange combination
        else:
            raise ValueError(
                "Too many (in)equality signs present for constraint on line %d."
                % line_nr)
Пример #26
0
def init_model():
    global _MODEL
    _MODEL = Solver("No name", Solver.CBC_MIXED_INTEGER_PROGRAMMING)
Пример #27
0
def _set_coefficients(solver: pywraplp.Solver, objective_or_constraint,
                      coefficient_part: str, line_nr: int, var_names: set):

    # Strip the coefficient whitespace
    remainder = coefficient_part.strip()
    if len(remainder) == 0:
        raise ValueError("No variables present in equation on line %d." %
                         line_nr)

    # All variables found
    var_names_found = set()

    running_constant_sum = 0.0
    had_at_least_one_variable = False
    while len(remainder) != 0:

        # Combination sign
        coefficient = 1.0
        combination_sign_match = re.search(r"^[-+]", remainder)
        if combination_sign_match is not None:
            if combination_sign_match.group() == "-":
                coefficient = -1.0
            remainder = remainder[1:].strip()

        # Real sign
        sign_match = re.search(r"^[-+]", remainder)
        if sign_match is not None:
            if sign_match.group() == "-":
                coefficient = coefficient * -1.0
            remainder = remainder[
                1:]  # There is no strip() here, as it must be directly in front of the mantissa

        # Mantissa and exponent
        mantissa_exp_match = re.search(r"^(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?",
                                       remainder)
        whitespace_after = False
        if mantissa_exp_match is not None:
            coefficient = coefficient * float(mantissa_exp_match.group())
            remainder = remainder[mantissa_exp_match.span()[1]:]
            stripped_remainder = remainder.strip()
            if len(remainder) != len(stripped_remainder):
                whitespace_after = True
            remainder = stripped_remainder

        # Variable name
        var_name_match = re.search(_REGEXP_SINGLE_VAR_NAME_START, remainder)
        if var_name_match is not None:

            # It must have had at least one variable
            had_at_least_one_variable = True

            # Retrieve clean variable name
            clean_var = var_name_match.group()
            var_names.add(clean_var)
            if clean_var in var_names_found:
                raise ValueError(
                    "Variable \"%s\" found more than once on line %d." %
                    (clean_var, line_nr))
            var_names_found.add(clean_var)
            solver_var = solver.LookupVariable(clean_var)
            if solver_var is None:
                solver_var = solver.NumVar(-solver.infinity(),
                                           solver.infinity(), clean_var)

            # Set coefficient
            objective_or_constraint.SetCoefficient(solver_var, coefficient)

            # Strip what we matched
            remainder = remainder[var_name_match.span()[1]:]
            stripped_remainder = remainder.strip()
            whitespace_after = False
            if len(remainder) != len(stripped_remainder):
                whitespace_after = True
            remainder = stripped_remainder

        elif mantissa_exp_match is None:
            raise ValueError(
                "Cannot process remainder coefficients of \"%s\" on line %d." %
                (remainder, line_nr))

        else:
            running_constant_sum += coefficient

        # At the end of each element there either:
        # (a) Must be whitespace (e.g., x1 x2 <= 10)
        # (b) The next combination sign (e.g., x1+x2 <= 10)
        # (c) Or it was the last one, as such remainder is empty (e.g., x1 <= 10)
        if len(remainder) != 0 and not whitespace_after and remainder[
                0:1] != "-" and remainder[0:1] != "+":
            raise ValueError(
                "Unexpected next character \"%s\" on line %d (expected whitespace or "
                "combination sign character)." % (remainder[0:1], line_nr))

    # There must have been at least one variable
    if not had_at_least_one_variable:
        raise ValueError(
            "Not a single variable present in the coefficients on line %d." %
            line_nr)

    return running_constant_sum