Ejemplo n.º 1
0
def create_linear_constraints_min_calorie(variables, prod_values, req_values):
    """
    Function returns list of linear constraints needed to satisfy requirements. Every constraint
    should include min and max for nutrient and all variables multiplied by amount of nutrient in
    given product.
    :param variables: dictionary containing names and LpVariables
    :param prod_values: dictionary of dictionaries containing name and nutrients values
    :param req_values: dictionary of pairs containing requirements for nutrients
    :return: list of linear constraints
    """
    constraints = list()
    # Student implementation below.
    constr = 0
    for j in req_values.keys():
        constr = LpConstraint(e=None,
                              sense=1,
                              name=constr,
                              rhs=req_values[j][0])
        for i in variables:
            constr += variables[i] * prod_values[i][j]
        constraints.append(constr)
        constr = LpConstraint(e=None,
                              sense=-1,
                              name=constr,
                              rhs=req_values[j][1])
        for i in variables:
            constr += variables[i] * prod_values[i][j]
        constraints.append(constr)
    return constraints[2:]
    raise NotImplementedError()
Ejemplo n.º 2
0
 def _make_single_assignment_constraints(lhs_single: list,
                                         kind: str) -> list:
     constraints_single = [
         LpConstraint(e=lhs_s,
                      sense=-1,
                      name=f"constraint_single_{kind}_{i}",
                      rhs=1) for i, lhs_s in enumerate(lhs_single)
     ]
     return constraints_single
Ejemplo n.º 3
0
def addline(m, p1, p2, x, y, upper=True):
    """2点直線制約"""
    from pulp import LpConstraint, LpConstraintGE, LpConstraintLE
    dx = p2[0] - p1[0]
    if dx != 0:
        m += LpConstraint(
            y - (p2[1] - p1[1]) / dx * x -
            (p2[0] * p1[1] - p1[0] * p2[1]) / dx,
            LpConstraintGE if upper else LpConstraintLE)
Ejemplo n.º 4
0
    def add_constraint(self, expr, relation, value, name=None):
        """
        Add a constraint to the model
        """
        if relation == '==':
            pulp_relation = LpConstraintEQ
        elif relation == '<=':
            pulp_relation = LpConstraintLE
        elif relation == '>=':
            pulp_relation = LpConstraintGE
        else:
            raise Exception("relation must be either '==' or '>=' or '<='")

        self.model += LpConstraint(e=expr,
                                   sense=pulp_relation,
                                   rhs=value,
                                   name=name)
Ejemplo n.º 5
0
def random_model(nv,
                 nc,
                 sense=1,
                 seed=1,
                 rtfr=0,
                 rtco=0.1,
                 rteq=0,
                 feasible=False):
    """
    ランダムなLP作成
    nv,nc:変数数、制約条件数
    sense:種類(LpMinimize=1)
    seed:乱数シード
    rtfr:自由変数割合
    rtco:係数行列非零割合
    rteq:制約条件等号割合
    feasible:実行可能かどうか
    """
    from pulp import LpConstraint, LpStatusOptimal

    rtco = max(1e-3, rtco)
    if seed:
        np.random.seed(seed)
    var_count = [0]
    x = np.array(addvars(nv, var_count=var_count))
    while True:
        m = LpProblem(sense=sense)
        m += lpDot(np.random.rand(nv) * 2 - 1, x)
        for v in x[np.random.rand(nv) < rtfr]:
            v.lowBound = None
        rem = nc
        while rem > 0:
            a = np.random.rand(nv) * 2 - 1
            a[np.random.rand(nv) >= rtco] = 0
            if (a == 0).all():
                continue
            if (a <= 0).all():
                a = -a
            se = int(np.random.rand() >= rteq) * np.random.choice([-1, 1])
            m += LpConstraint(lpDot(a, x), se, rhs=np.random.rand())
            rem -= 1
        if not feasible or m.solve() == LpStatusOptimal:
            return m
Ejemplo n.º 6
0
    def _get_feasibility_constraints(self) -> list:
        tups = [(i, j) for i in range(self.n) for j in range(self.n)]

        # Left-hand side
        lhs_like = [
            LpAffineExpression([(self.x_np[tup[0], tup[1]], 1)],
                               name=f"lhs_like_{tup[0]}_{tup[1]}")
            for tup in tups
        ]

        # Constraints
        constraints_like = [
            LpConstraint(
                e=lhs_l,
                sense=-1,
                name=f"constraint_like_{tups[i][0]}_{tups[i][1]}",
                rhs=self.match_matrix[tups[i][0], tups[i][1]],
            ) for i, lhs_l in enumerate(lhs_like)
        ]
        return constraints_like
Ejemplo n.º 7
0
    def _get_symmetry_constraints(self) -> list:
        tups = [(i, j) for i in range(self.n) for j in range(i + 1, self.n)]

        # Left-hand side
        lhs_symmetry = [
            LpAffineExpression(
                [(self.x_np[tup[0], tup[1]], 1),
                 (self.x_np[tup[1], tup[0]], -1)],
                name=f"lhs_sym_{tup[0]}_{tup[1]}",
            ) for tup in tups
        ]

        # Constraints
        constraints_symmetry = [
            LpConstraint(
                e=lhs_s,
                sense=0,
                name=f"constraint_sym_{tups[i][0]}_{tups[i][1]}",
                rhs=0,
            ) for i, lhs_s in enumerate(lhs_symmetry)
        ]
        return constraints_symmetry
Ejemplo n.º 8
0
def BranchAndBound(T, CONSTRAINTS, VARIABLES, OBJ, MAT, RHS,
                   branch_strategy = MOST_FRACTIONAL,
                   search_strategy = DEPTH_FIRST,
                   complete_enumeration = False,
                   display_interval = None,
                   binary_vars = True):
    
    if T.get_layout() == 'dot2tex':
        cluster_attrs = {'name':'Key', 'label':r'\text{Key}', 'fontsize':'12'}
        T.add_node('C', label = r'\text{Candidate}', style = 'filled',
                      color = 'yellow', fillcolor = 'yellow')
        T.add_node('I', label = r'\text{Infeasible}', style = 'filled',
                      color = 'orange', fillcolor = 'orange')
        T.add_node('S', label = r'\text{Solution}', style = 'filled',
                      color = 'lightblue', fillcolor = 'lightblue')
        T.add_node('P', label = r'\text{Pruned}', style = 'filled',
                      color = 'red', fillcolor = 'red')
        T.add_node('PC', label = r'\text{Pruned}$\\ $\text{Candidate}', style = 'filled',
                      color = 'red', fillcolor = 'yellow')
    else:
        cluster_attrs = {'name':'Key', 'label':'Key', 'fontsize':'12'}
        T.add_node('C', label = 'Candidate', style = 'filled',
                      color = 'yellow', fillcolor = 'yellow')
        T.add_node('I', label = 'Infeasible', style = 'filled',
                      color = 'orange', fillcolor = 'orange')
        T.add_node('S', label = 'Solution', style = 'filled',
                      color = 'lightblue', fillcolor = 'lightblue')
        T.add_node('P', label = 'Pruned', style = 'filled',
                      color = 'red', fillcolor = 'red')
        T.add_node('PC', label = 'Pruned \n Candidate', style = 'filled',
                      color = 'red', fillcolor = 'yellow')
    T.add_edge('C', 'I', style = 'invisible', arrowhead = 'none')
    T.add_edge('I', 'S', style = 'invisible', arrowhead = 'none')
    T.add_edge('S', 'P', style = 'invisible', arrowhead = 'none')
    T.add_edge('P', 'PC', style = 'invisible', arrowhead = 'none')
    T.create_cluster(['C', 'I', 'S', 'P', 'PC'], cluster_attrs)
    # The initial lower bound
    LB = -INFINITY
    # The number of LP's solved, and the number of nodes solved
    node_count = 1
    iter_count = 0
    lp_count = 0
    
    if binary_vars:
        var   = LpVariable.dicts("", VARIABLES, 0, 1)
    else:
        var   = LpVariable.dicts("", VARIABLES)
    
    numCons = len(CONSTRAINTS)
    numVars = len(VARIABLES)
    # List of incumbent solution variable values
    opt = dict([(i, 0) for i in VARIABLES])
    pseudo_u = dict((i, (OBJ[i], 0)) for i in VARIABLES)
    pseudo_d = dict((i, (OBJ[i], 0)) for i in VARIABLES)
    print("===========================================")
    print("Starting Branch and Bound")
    if branch_strategy == MOST_FRACTIONAL:
        print("Most fractional variable")
    elif branch_strategy == FIXED_BRANCHING:
        print("Fixed order")
    elif branch_strategy == PSEUDOCOST_BRANCHING:
        print("Pseudocost brancing")
    else:
        print("Unknown branching strategy %s" %branch_strategy)
    if search_strategy == DEPTH_FIRST:
        print("Depth first search strategy")
    elif search_strategy == BEST_FIRST:
        print("Best first search strategy")
    else:
        print("Unknown search strategy %s" %search_strategy)
    print("===========================================")
    # List of candidate nodes
    Q = PriorityQueue()
    # The current tree depth
    cur_depth = 0
    cur_index = 0
    # Timer
    timer = time.time()
    Q.push(0, -INFINITY, (0, None, None, None, None, None, None))
    # Branch and Bound Loop
    while not Q.isEmpty():
        infeasible = False
        integer_solution = False
        (cur_index, parent, relax, branch_var, branch_var_value, sense,
        rhs) = Q.pop()
        if cur_index != 0:
            cur_depth = T.get_node_attr(parent, 'level') + 1
        else:
            cur_depth = 0
        print("")
        print("----------------------------------------------------")
        print("")
        if LB > -INFINITY:
            print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,LB))
        else:
            print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,"None"))
        if relax is not None and relax <= LB:
            print("Node pruned immediately by bound")
            T.set_node_attr(parent, 'color', 'red')
            continue
        #====================================
        #    LP Relaxation
        #====================================
        # Compute lower bound by LP relaxation
        prob = LpProblem("relax", LpMaximize)
        prob += lpSum([OBJ[i]*var[i] for i in VARIABLES]), "Objective"
        for j in range(numCons):
            prob += (lpSum([MAT[i][j]*var[i] for i in VARIABLES])<=RHS[j],\
                         CONSTRAINTS[j])
        # Fix all prescribed variables
        branch_vars = []
        if cur_index != 0:
            sys.stdout.write("Branching variables: ")
            branch_vars.append(branch_var)
            if sense == '>=':
                prob += LpConstraint(lpSum(var[branch_var]) >= rhs)
            else:
                prob += LpConstraint(lpSum(var[branch_var]) <= rhs)
            print(branch_var, end=' ')
            pred = parent
            while not str(pred) == '0':
                pred_branch_var = T.get_node_attr(pred, 'branch_var')
                pred_rhs = T.get_node_attr(pred, 'rhs')
                pred_sense = T.get_node_attr(pred, 'sense')
                if pred_sense == '<=':
                    prob += LpConstraint(lpSum(var[pred_branch_var])
                                         <= pred_rhs)
                else:
                    prob += LpConstraint(lpSum(var[pred_branch_var])
                                         >= pred_rhs)
                print(pred_branch_var, end=' ')
                branch_vars.append(pred_branch_var)
                pred = T.get_node_attr(pred, 'parent')
            print()
        # Solve the LP relaxation
        prob.solve()
        lp_count = lp_count +1
        # Check infeasibility
        infeasible = LpStatus[prob.status] == "Infeasible" or \
            LpStatus[prob.status] == "Undefined"
        # Print status
        if infeasible:
            print("LP Solved, status: Infeasible")
        else:
            print("LP Solved, status: %s, obj: %s" %(LpStatus[prob.status],
                                                     value(prob.objective)))
        if(LpStatus[prob.status] == "Optimal"):
            relax = value(prob.objective)
            # Update pseudocost
            if branch_var != None:
                if sense == '<=':
                    pseudo_d[branch_var] = (
                    old_div((pseudo_d[branch_var][0]*pseudo_d[branch_var][1] +
                    old_div((T.get_node_attr(parent, 'obj') - relax),
                    (branch_var_value - rhs))),(pseudo_d[branch_var][1]+1)),
                    pseudo_d[branch_var][1]+1)
                else:
                    pseudo_u[branch_var] = (
                    old_div((pseudo_u[branch_var][0]*pseudo_d[branch_var][1] +
                     old_div((T.get_node_attr(parent, 'obj') - relax),
                     (rhs - branch_var_value))),(pseudo_u[branch_var][1]+1)),
                    pseudo_u[branch_var][1]+1)
            var_values = dict([(i, var[i].varValue) for i in VARIABLES])
            integer_solution = 1
            for i in VARIABLES:
                if (abs(round(var_values[i]) - var_values[i]) > .001):
                    integer_solution = 0
                    break
            # Determine integer_infeasibility_count and
            # Integer_infeasibility_sum for scatterplot and such
            integer_infeasibility_count = 0
            integer_infeasibility_sum = 0.0
            for i in VARIABLES:
                if (var_values[i] not in set([0,1])):
                    integer_infeasibility_count += 1
                    integer_infeasibility_sum += min([var_values[i],
                                                      1.0-var_values[i]])
            if (integer_solution and relax>LB):
                LB = relax
                for i in VARIABLES:
                    # These two have different data structures first one
                    #list, second one dictionary
                    opt[i] = var_values[i]
                print("New best solution found, objective: %s" %relax)
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            elif (integer_solution and relax<=LB):
                print("New integer solution found, objective: %s" %relax)
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            else:
                print("Fractional solution:")
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            #For complete enumeration
            if complete_enumeration:
                relax = LB - 1
        else:
            relax = INFINITY
        if integer_solution:
            print("Integer solution")
            BBstatus = 'S'
            status = 'integer'
            color = 'lightblue'
        elif infeasible:
            print("Infeasible node")
            BBstatus = 'I'
            status = 'infeasible'
            color = 'orange'
        elif not complete_enumeration and relax <= LB:
            print("Node pruned by bound (obj: %s, UB: %s)" %(relax,LB))
            BBstatus = 'P'
            status = 'fathomed'
            color = 'red'
        elif cur_depth >= numVars :
            print("Reached a leaf")
            BBstatus = 'fathomed'
            status = 'L'
        else:
            BBstatus = 'C'
            status = 'candidate'
            color = 'yellow'
        if BBstatus == 'I':
            if T.get_layout() == 'dot2tex':
                label = r'\text{I}'
            else:
                label = 'I'
        else:
            label = "%.1f"%relax
        if iter_count == 0:
            if status != 'candidate':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            if status == 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before '+\
                        'first incumbent.')
            T.AddOrUpdateNode(0, None, None, 'candidate', relax,
                             integer_infeasibility_count,
                             integer_infeasibility_sum,
                             label = label,
                             obj = relax, color = color,
                             style = 'filled', fillcolor = color)
            if status == 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = -1
                T._new_integer_solution = True
#           #Currently broken
#           if ETREE_INSTALLED and T.attr['display'] == 'svg':
#               T.write_as_svg(filename = "node%d" % iter_count,
#                                 nextfile = "node%d" % (iter_count + 1),
#                                 highlight = cur_index)
        else:
            _direction = {'<=':'L', '>=':'R'}
            if status == 'infeasible':
                integer_infeasibility_count = T.get_node_attr(parent,
                                     'integer_infeasibility_count')
                integer_infeasibility_sum = T.get_node_attr(parent,
                                     'integer_infeasibility_sum')
                relax = T.get_node_attr(parent, 'lp_bound')
            elif status == 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before'+\
                        ' first incumbent.')
                    print('  This may indicate an error in the input file.')
            elif status == 'integer':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            T.AddOrUpdateNode(cur_index, parent, _direction[sense],
                                 status, relax,
                                 integer_infeasibility_count,
                                 integer_infeasibility_sum,
                                 branch_var = branch_var,
                                 branch_var_value = var_values[branch_var],
                                 sense = sense, rhs = rhs, obj = relax,
                                 color = color, style = 'filled',
                                 label = label, fillcolor = color)
            if status == 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = parent
                T._new_integer_solution = True
            # Currently Broken
#           if ETREE_INSTALLED and T.attr['display'] == 'svg':
#               T.write_as_svg(filename = "node%d" % iter_count,
#                                 prevfile = "node%d" % (iter_count - 1),
#                                 nextfile = "node%d" % (iter_count + 1),
#                                 highlight = cur_index)
            if T.get_layout() == 'dot2tex':
                _dot2tex_label = {'>=':' \geq ', '<=':' \leq '}
                T.set_edge_attr(parent, cur_index, 'label',
                                   str(branch_var) + _dot2tex_label[sense] +
                                   str(rhs))
            else:
                T.set_edge_attr(parent, cur_index, 'label',
                                   str(branch_var) + sense + str(rhs))
        iter_count += 1
        if BBstatus == 'C':
            # Branching:
            # Choose a variable for branching
            branching_var = None
            if branch_strategy == FIXED_BRANCHING:
                #fixed order
                for i in VARIABLES:
                    frac = min(var[i].varValue-math.floor(var[i].varValue),
                               math.ceil(var[i].varValue) - var[i].varValue)
                    if (frac > 0):
                        min_frac = frac
                        branching_var = i
                        # TODO(aykut): understand this break
                        break
            elif branch_strategy == MOST_FRACTIONAL:
                #most fractional variable
                min_frac = -1
                for i in VARIABLES:
                    frac = min(var[i].varValue-math.floor(var[i].varValue),
                               math.ceil(var[i].varValue)- var[i].varValue)
                    if (frac> min_frac):
                        min_frac = frac
                        branching_var = i
            elif branch_strategy == PSEUDOCOST_BRANCHING:
                scores = {}
                for i in VARIABLES:
                    # find the fractional solutions
                    if (var[i].varValue - math.floor(var[i].varValue)) != 0:
                        scores[i] = min(pseudo_u[i][0]*(1-var[i].varValue),
                                        pseudo_d[i][0]*var[i].varValue)
                    # sort the dictionary by value
                branching_var = sorted(list(scores.items()),
                                       key=lambda x : x[1])[-1][0]
            else:
                print("Unknown branching strategy %s" %branch_strategy)
                exit()
            if branching_var is not None:
                print("Branching on variable %s" %branching_var)
            #Create new nodes
            if search_strategy == DEPTH_FIRST:
                priority = (-cur_depth - 1, -cur_depth - 1)
            elif search_strategy == BEST_FIRST:
                priority = (-relax, -relax)
            elif search_strategy == BEST_ESTIMATE:
                priority = (-relax - pseudo_d[branching_var][0]*\
                                 (math.floor(var[branching_var].varValue) -\
                                      var[branching_var].varValue),
                            -relax + pseudo_u[branching_var][0]*\
                                 (math.ceil(var[branching_var].varValue) -\
                                      var[branching_var].varValue))
            node_count += 1
            Q.push(node_count, priority[0], (node_count, cur_index, relax, branching_var,
                    var_values[branching_var],
                    '<=', math.floor(var[branching_var].varValue)))
            node_count += 1
            Q.push(node_count, priority[1], (node_count, cur_index, relax, branching_var,
                    var_values[branching_var],
                    '>=', math.ceil(var[branching_var].varValue)))
            T.set_node_attr(cur_index, color, 'green')
        if T.root is not None and display_interval is not None and\
                iter_count%display_interval == 0:
            T.display(count=iter_count)

    timer = int(math.ceil((time.time()-timer)*1000))
    print("")
    print("===========================================")
    print("Branch and bound completed in %sms" %timer)
    print("Strategy: %s" %branch_strategy)
    if complete_enumeration:
        print("Complete enumeration")
    print("%s nodes visited " %node_count)
    print("%s LP's solved" %lp_count)
    print("===========================================")
    print("Optimal solution")
    #print optimal solution
    for i in sorted(VARIABLES):
        if opt[i] > 0:
            print("%s = %s" %(i, opt[i]))
    print("Objective function value")
    print(LB)
    print("===========================================")
    if T.attr['display'] != 'off':
        T.display(count=iter_count)
    T._lp_count = lp_count
    return opt, LB
Ejemplo n.º 9
0
    #    LP Relaxation
    #====================================
    #Compute lower bound by LP relaxation
    prob = LpProblem("relax", LpMaximize)
    prob += lpSum([OBJ[i] * var[i] for i in VARIABLES]), "Objective"
    for j in range(numCons):
        prob += lpSum([MAT[i][j]*var[i] for i in VARIABLES]) <= RHS[j], \
            CONSTRAINTS[j]

    #Fix all prescribed variables
    branch_vars = []
    if cur_index is not 0:
        print("Branching variables: ")
        branch_vars.append(branch_var)
        if sense == '>=':
            prob += LpConstraint(lpSum(var[branch_var]) >= rhs)
        else:
            prob += LpConstraint(lpSum(var[branch_var]) <= rhs)
        print(branch_var, end=' ')
        pred = parent
        while str(pred) is not '0':
            pred_branch_var = T.get_node_attr(pred, 'branch_var')
            pred_rhs = T.get_node_attr(pred, 'rhs')
            pred_sense = T.get_node_attr(pred, 'sense')
            if pred_sense == '<=':
                prob += LpConstraint(lpSum(var[pred_branch_var]) <= pred_rhs)
            else:
                prob += LpConstraint(lpSum(var[pred_branch_var]) >= pred_rhs)
            print(pred_branch_var, end=' ')
            branch_vars.append(pred_branch_var)
            pred = T.get_node_attr(pred, 'parent')
Ejemplo n.º 10
0
def solve_diet_min_calorie(prod_values, req_values):
    """
    Function creates and sets up linear programming problem for calorie minimization.
    Returns problem, objective value and solver status.
    :param prod_values: dictionary of dictionaries containing name and nutrients values
    :param req_values: dictionary of pairs containing requirements for nutrients
    :return: (LpProblem, LpObjective, LpStatus)
    """
    # Student implementation below.
    products_names = list(prod_values.keys())
    nutrients = ['calorie', 'proteins', 'carbs', 'sugar', 'fat']
    prob = LpProblem('Diet problem', LpMinimize)
    calories = []
    proteins = []
    carbs = []
    sugar = []
    fat = []
    constraints = []
    for i in range(10):
        tmp = prod_values[products_names[i]]
        calories.append(tmp['calorie'])
        proteins.append(tmp['proteins'])
        carbs.append(tmp['carbs'])
        sugar.append(tmp['sugar'])
        fat.append(tmp['fat'])
    calories = list_to_dict(products_names, calories)
    proteins = list_to_dict(products_names, proteins)
    carbs = list_to_dict(products_names, carbs)
    sugar = list_to_dict(products_names, sugar)
    fat = list_to_dict(products_names, fat)

    food_vars = LpVariable.dicts("Food", products_names, lowBound=0)
    problem = LpProblem('Diet problem', LpMinimize)
    prob = LpProblem('Diet problem', LpMinimize)
    prob += lpSum([calories[i] * food_vars[i] for i in products_names])
    objective = lpSum([calories[i] * food_vars[i] for i in products_names])

    prob += LpConstraint(lpSum([food_vars[f] for f in products_names]) >= 0)

    prob += LpConstraint(
        lpSum([calories[f] * food_vars[f]
               for f in products_names]) >= req_values['calorie'][0])
    prob += LpConstraint(
        lpSum([calories[f] * food_vars[f]
               for f in products_names]) <= req_values['calorie'][1])

    prob += LpConstraint(
        lpSum([proteins[f] * food_vars[f]
               for f in products_names]) >= req_values['proteins'][0])
    prob += LpConstraint(
        lpSum([proteins[f] * food_vars[f]
               for f in products_names]) <= req_values['proteins'][1])

    prob += LpConstraint(
        lpSum([carbs[f] * food_vars[f]
               for f in products_names]) >= req_values['carbs'][0])
    prob += LpConstraint(
        lpSum([carbs[f] * food_vars[f]
               for f in products_names]) <= req_values['carbs'][1])

    prob += LpConstraint(
        lpSum([sugar[f] * food_vars[f]
               for f in products_names]) >= req_values['sugar'][0])
    prob += LpConstraint(
        lpSum([sugar[f] * food_vars[f]
               for f in products_names]) <= req_values['sugar'][1])

    prob += LpConstraint(
        lpSum([fat[f] * food_vars[f]
               for f in products_names]) >= req_values['fat'][0])
    prob += LpConstraint(
        lpSum([fat[f] * food_vars[f]
               for f in products_names]) <= req_values['fat'][1])
    prob.solve()

    return prob, food_vars, 1
Ejemplo n.º 11
0
def create_linear_constraints_min_calorie(
        variables, prod_values, req_values):  #TestConstraintsMinCalorie
    """
    Function returns list of linear constraints needed to satisfy requirements. Every constraint
    should include min and max for nutrient and all variables multiplied by amount of nutrient in
    given product.
    :param variables: dictionary containing names and LpVariables
    :param prod_values: dictionary of dictionaries containing name and nutrients values
    :param req_values: dictionary of pairs containing requirements for nutrients
    :return: list of linear constraints
    """
    constraints = []
    # Student implementation below.
    products_names = list(prod_values.keys())
    nutrients = ['calorie', 'proteins', 'carbs', 'sugar', 'fat']
    prob = LpProblem('Diet problem', LpMinimize)
    calories = []
    proteins = []
    carbs = []
    sugar = []
    fat = []
    for i in range(10):
        tmp = prod_values[products_names[i]]
        calories.append(tmp['calorie'])
        proteins.append(tmp['proteins'])
        carbs.append(tmp['carbs'])
        sugar.append(tmp['sugar'])
        fat.append(tmp['fat'])
    calories = list_to_dict(products_names, calories)
    proteins = list_to_dict(products_names, proteins)
    carbs = list_to_dict(products_names, carbs)
    sugar = list_to_dict(products_names, sugar)
    fat = list_to_dict(products_names, fat)
    food_vars = LpVariable.dicts("Food", products_names, lowBound=0)
    constraints.append(
        LpConstraint(
            lpSum([calories[f] * food_vars[f]
                   for f in products_names]) >= req_values['calorie'][0]))
    constraints.append(
        LpConstraint(
            lpSum([calories[f] * food_vars[f]
                   for f in products_names]) <= req_values['calorie'][1]))

    constraints.append(
        LpConstraint(
            lpSum([proteins[f] * food_vars[f]
                   for f in products_names]) >= req_values['proteins'][0]))
    constraints.append(
        LpConstraint(
            lpSum([proteins[f] * food_vars[f]
                   for f in products_names]) <= req_values['proteins'][1]))
    constraints.append(
        LpConstraint(
            lpSum([carbs[f] * food_vars[f]
                   for f in products_names]) >= req_values['carbs'][0]))
    constraints.append(
        LpConstraint(
            lpSum([carbs[f] * food_vars[f]
                   for f in products_names]) <= req_values['carbs'][1]))

    constraints.append(
        LpConstraint(
            lpSum([sugar[f] * food_vars[f]
                   for f in products_names]) >= req_values['sugar'][0]))
    constraints.append(
        LpConstraint(
            lpSum([sugar[f] * food_vars[f]
                   for f in products_names]) <= req_values['sugar'][1]))

    constraints.append(
        LpConstraint(
            lpSum([fat[f] * food_vars[f]
                   for f in products_names]) >= req_values['fat'][0]))
    constraints.append(
        LpConstraint(
            lpSum([fat[f] * food_vars[f]
                   for f in products_names]) <= req_values['fat'][1]))

    return constraints
Ejemplo n.º 12
0
from pulp import LpProblem, LpVariable, LpConstraint, LpConstraintLE, LpConstraintGE, LpMaximize, LpBinary, LpStatus

# Create a new model
m = LpProblem(name="MIP Model", sense=LpMaximize)

# Create variables
x = LpVariable(cat=LpBinary, name="x")
y = LpVariable(cat=LpBinary, name="y")
z = LpVariable(cat=LpBinary, name="z")

# Add constraint: x + 2 y + 3 z <= 4
m += LpConstraint(e=(x + 2 * y + 3 * z),
                  sense=LpConstraintLE,
                  rhs=4,
                  name='c0')

# Add constraint: x + y >= 1
m += LpConstraint(e=(x + y), sense=LpConstraintGE, rhs=1, name='c1')

# Set objective
m.setObjective(x + y + 2 * z)

# Calculate with the default CBC optimizer
status = m.solve()

if LpStatus[status] == 'Optimal':

    for v in m.variables():
        print('%s %g' % (v.name, v.varValue))

    print('Obj: %g' % m.objective.value())
def ilp_solve(co_occur_matrix,
              weights,
              lengths,
              max_length=None,
              concepts_discrete=True):
    """
    co_occur_matrix  : A, Co-occurence matrix of dimensions NxM
    weights          : w, List of length N of Weight values (float)
    lengths          : l, List of length M of sentence lengths (int)
    max_length       : L, If set to some number, max. length cannot be greater than L
    concepts_discrete: Set to True if z should be discrete in [0,1] and False
                      if z should be continuous
    
    # Change this to return only 'y' later
    Returns a dict with 'y' and 'z' as keys. 'y' contains a list (size M) of 0s and 1s
    to say if a sentence should be included or not. 'z' the same but for concepts
    from 1 to N. 
    """
    # Smaller variable names
    A = co_occur_matrix
    w = weights
    l = lengths

    # N represents concepts, M represents sentences
    N = len(A)
    M = len(A[0])
    L = max_length

    if len(w) != N:
        raise ValueError("weights not the same dimension as A[rows]")
    if L and len(l) != M:
        raise ValueError("lengths not the same dimension as A[cols]")

    # Target variables
    # y[i] decides if sentence[i] is included or not. Only Binary values allowed
    y = [LpVariable("y%s" % i, 0, 1, LpInteger) for i in range(M)]
    # z[i] decides if concept[j] is included or not.
    args = [LpInteger] if concepts_discrete else []
    z = [LpVariable("z%s" % i, 0, 1, *args) for i in range(N)]

    # Objective function
    problem = LpProblem("Class Evaluation Summary", LpMaximize)
    problem += lpSum([w[i] * z[i] for i in range(N)]), "Obj. function"

    # Constraints
    for i in range(N):
        problem += lpSum([A[i][j] * y[j] for j in range(M)]) >= z[
            i], "z cond 1 (i) -> sum_{j=0_to_M-1}(A[%s][j]y[j] >= z[%s]" % (i,
                                                                            i)
        for j in range(M):
            problem += LpConstraint(
                A[i][j] <=
                z[i])  #, "z cond 2 (i,j) -> A[%s][%s] <= z[%s]" % (i,j,i)

    if L:
        problem += lpSum([l[j] * y[j]
                          for j in range(M)]) <= L, "length constraint"

    # Solve
    problem.solve()

    # Assign and return
    res_y = [0 for i in range(M)]
    res_z = [0 for i in range(N)]
    for var in problem.variables():
        char, index = var.name[0], int(var.name[1:])
        if char == 'y':
            res_y[index] = var.varValue
        elif char == 'z':
            res_z[index] = var.varValue

    return {'y': res_y, 'z': res_z}