示例#1
0
def ilp(prods, n_prods, alpha):
    S1, S2, S3, S4 = segregate(prods, n_prods, alpha)
    x = np.array([0.0 for i in range(n_prods)])
    d = 0
    for prod in S1:
        x[prod.index] = 1
        d = d + (prod.q - alpha)
    rev = [-1.0 for i in range(n_prods)]
    qdiff = [-1.0 for i in range(n_prods)]
    for prod in S2:
        ind = prod.index
        rev[ind] = prod.r
        qdiff[ind] = prod.q - alpha
    for prod in S3:
        ind = prod.index
        rev[ind] = prod.r
        qdiff[ind] = prod.q - alpha

    m = Model('ilp')
    m.verbose = False
    y = [m.add_var(var_type=BINARY) for i in range(n_prods)]
    m.objective = maximize(xsum(rev[i] * y[i] for i in range(n_prods)))
    m += xsum(qdiff[i] * y[i] for i in range(n_prods)) >= -1 * d
    m.optimize()
    selected = np.array([y[i].x for i in range(n_prods)])
    import pdb
    pdb.set_trace()
    selected = np.floor(selected + 0.01)
    import pdb
    pdb.set_trace()
    return x + selected, d
示例#2
0
    def set_opt_model_func(model, profile, in_committee, committeesize):
        load = {}
        for cand in profile.candidates:
            for i, voter in enumerate(profile):
                load[(voter, cand)] = model.add_var(lb=0.0,
                                                    ub=1.0,
                                                    var_type=mip.CONTINUOUS,
                                                    name=f"load{i}-{cand}")

        # constraint: the committee has the required size
        model += mip.xsum(in_committee[cand]
                          for cand in profile.candidates) == committeesize

        for cand in profile.candidates:
            for voter in profile:
                if cand not in voter.approved:
                    load[(voter, cand)] = 0

        # a candidate's load is distributed among his approvers
        for cand in profile.candidates:
            model += (mip.xsum(
                voter.weight * load[(voter, cand)] for voter in profile
                if cand in profile.candidates) >= in_committee[cand])

        loadbound = model.add_var(lb=0,
                                  ub=committeesize,
                                  var_type=mip.CONTINUOUS,
                                  name="loadbound")
        for voter in profile:
            model += mip.xsum(load[(voter, cand)]
                              for cand in voter.approved) <= loadbound

        # maximizing the negative distance makes code more similar to the other methods here
        model.objective = mip.maximize(-loadbound)
示例#3
0
    def set_opt_model_func(model, profile, in_committee, committeesize,
                           previously_found_committees, scorefct):
        max_hamming_distance = model.add_var(
            var_type=mip.INTEGER,
            lb=0,
            ub=profile.num_cand,
            name="max_hamming_distance",
        )

        model += mip.xsum(in_committee[cand]
                          for cand in profile.candidates) == committeesize

        for voter in profile:
            not_approved = [
                cand for cand in profile.candidates
                if cand not in voter.approved
            ]
            # maximum Hamming distance is greater of equal than the Hamming distances
            # between individual voters and the committee
            model += max_hamming_distance >= mip.xsum(
                1 - in_committee[cand] for cand in voter.approved) + mip.xsum(
                    in_committee[cand] for cand in not_approved)

        # find a new committee that has not been found before
        for committee in previously_found_committees:
            model += mip.xsum(in_committee[cand]
                              for cand in committee) <= committeesize - 1

        # maximizing the negative distance makes code more similar to the other methods here
        model.objective = mip.maximize(-max_hamming_distance)
def do_matching(graph, visualize=True):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()

    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[original, u] = weight

    if visualize:
        graph = nx.Graph()
        graph.add_nodes_from(V)
        graph.add_edges_from(E)
        nx.draw_kamada_kawai(graph)
        plt.show()

    model = Model("Maximum matching")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    for v in V:
        model += xsum(edge_vars[s, t] for s, t in E if v in [s, t]) <= 1
    model.objective = maximize(
        xsum(
            xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) *
                 edge_vars[edge] for edge in E) for edge in E))
    model.optimize(max_seconds=300)
    return sorted([e for e in E if edge_vars[e].x > .01])
def mip_optimization(cal_df, y, constrain=3, daily_weights=None):
    """Mixed integer linear programming optimization with constraints.
    Args:
        y (numpy.ndarray): sum of daily features (dim=#ofdays)
        constrain (int): minimum days in office
        daily_weights (array): weighting of days, e.g. if you prefer to come on mondays
    Return:
         
    """
    # daily weighting
    u = np.ones(len(y)) if daily_weights == None else daily_weights
    I = range(len(y))  # idx for days for summation

    m = Model("knapsack")  # MIP model
    w = [m.add_var(var_type=BINARY) for i in I]  # weights to optimize
    m.objective = maximize(xsum(y[i] * w[i]
                                for i in I))  # optimization function
    m += xsum(w[i] * u[i] for i in I) <= constrain  # constraint
    m.optimize()

    #selected = [i for i in I if w[i].x >= 0.99]
    selected = [w[i].x for i in I]

    df = pd.DataFrame(columns=["home_office"],
                      index=cal_df.index,
                      data={'home_office': selected})

    return df
示例#6
0
def test_knapsack(solver: str):
    p = [10, 13, 18, 31, 7, 15]
    w = [11, 15, 20, 35, 10, 33]
    c, I = 47, range(len(w))

    m = Model("knapsack", solver_name=solver)

    x = [m.add_var(var_type=BINARY) for i in I]

    m.objective = maximize(xsum(p[i] * x[i] for i in I))

    m += xsum(w[i] * x[i] for i in I) <= c, "cap"

    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == 41

    m.constr_by_name("cap").rhs = 60
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == 51

    # modifying objective function
    m.objective = m.objective + 10 * x[0] + 15 * x[1]
    assert abs(m.objective.expr[x[0]] - 20) <= 1e-10
    assert abs(m.objective.expr[x[1]] - 28) <= 1e-10
示例#7
0
def test_linexpr_x(solver: str, val: int):
    m = Model("bounds", solver_name=solver)

    x = m.add_var(lb=0, ub=2 * val)
    y = m.add_var(lb=val, ub=2 * val)
    obj = x - y

    assert obj.x is None  # No solution yet.

    m.objective = maximize(obj)
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == val
    assert round(x.x) == 2 * val
    assert round(y.x) == val

    # Check that the linear expression value is equal to the same expression
    # calculated from the values of the variables.
    assert abs((x + y).x - (x.x + y.x)) < TOL
    assert abs((x + 2 * y).x - (x.x + 2 * y.x)) < TOL
    assert abs((x + 2 * y + x).x - (x.x + 2 * y.x + x.x)) < TOL
    assert abs((x + 2 * y + x + 1).x - (x.x + 2 * y.x + x.x + 1)) < TOL
    assert abs((x + 2 * y + x + 1 + x / 2).x -
               (x.x + 2 * y.x + x.x + 1 + x.x / 2)) < TOL
示例#8
0
def knapsack():
    p = [10, 13, 18, 31, 7, 15]
    w = [11, 15, 20, 35, 10, 33]
    c, I = 47, range(len(w))

    m = Model("knapsack")
    x = [m.add_var(var_type=BINARY) for i in I]
    m.objective = maximize(xsum(p[i] * x[i] for i in I))
    m += xsum(w[i] * x[i] for i in I) <= c
    print(m.optimize())
def do_matching_stable(graph, visualize=True, individual=1, communal=10000000):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    if visualize:
        graph = nx.Graph()
        graph.add_nodes_from(V)
        graph.add_edges_from(E)
        nx.draw_kamada_kawai(graph)
        plt.show()

    model = Model("Rogue Couples based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]
    rogue_vars = {e: model.add_var(var_type=BINARY) for e in E}
    partners = dict()
    for v in V:
        partners[v] = model.add_var()
        partners[v] = xsum(edge_vars[s, t] for s, t in E if v in [s, t])
        model += partners[v] <= 1
    for (u, v), rogue_var in rogue_vars.items():
        v_primes = [
            vp for vp in outputs[u] if weights[(u, vp)] < weights[(u, v)]
        ]
        u_primes = [
            up for up in outputs[v] if weights[(v, up)] < weights[(v, u)]
        ]

        model += 1 - partners[v] - partners[u] + xsum(
            undirected[u, vp]
            for vp in v_primes) + xsum(undirected[up, v]
                                       for up in u_primes) <= rogue_var

    model.objective = maximize(individual * xsum(
        ((weights[edge] + weights[edge[1], edge[0]]) / 2) * edge_vars[edge]
        for edge in E) - communal * xsum(rogue_vars[edge] for edge in E))
    model.optimize(max_seconds=300)
    return sorted([e for e in E if edge_vars[e].x > .01])
示例#10
0
    def set_opt_model_func(model, profile, in_committee, committeesize,
                           previously_found_committees, scorefct):
        num_voters = len(profile)

        # optimization goal: variable "satisfaction"
        satisfaction = model.add_var(ub=num_voters,
                                     var_type=mip.INTEGER,
                                     name="satisfaction")

        model += mip.xsum(in_committee[cand]
                          for cand in profile.candidates) == committeesize

        # a partition of voters into `committeesize` many sets
        partition = {}
        for cand in profile.candidates:
            for voter in range(len(profile)):
                partition[(cand, voter)] = model.add_var(var_type=mip.BINARY,
                                                         name="partition")
        for voter in range(len(profile)):
            # every voter has to be part of a voter partition set
            model += mip.xsum(partition[(cand, voter)]
                              for cand in profile.candidates) == 1
        for cand in profile.candidates:
            # every voter set in the partition has to contain
            # at least (num_voters // committeesize) candidates
            model += mip.xsum(partition[(cand, voter)]
                              for voter in range(len(profile))) >= (
                                  num_voters // committeesize - num_voters *
                                  (1 - in_committee[cand]))
            # every voter set in the partition has to contain
            # at most ceil(num_voters/committeesize) candidates
            model += mip.xsum(
                partition[(cand, voter)] for voter in range(len(profile))) <= (
                    num_voters // committeesize +
                    bool(num_voters % committeesize) + num_voters *
                    (1 - in_committee[cand]))
            # if in_committee[i] = 0 then partition[(i,j) = 0
            model += (mip.xsum(partition[(cand, voter)]
                               for voter in range(len(profile))) <=
                      num_voters * in_committee[cand])

        # constraint for objective variable "satisfaction"
        model += (mip.xsum(partition[(cand, voter)] *
                           (cand in profile[voter].approved)
                           for voter in range(len(profile))
                           for cand in profile.candidates) >= satisfaction)

        # find a new committee that has not been found before
        for committee in previously_found_committees:
            model += mip.xsum(in_committee[cand]
                              for cand in committee) <= committeesize - 1

        # optimization objective
        model.objective = mip.maximize(satisfaction)
示例#11
0
def test_variable_bounds(solver: str, val: int):
    m = Model("bounds", solver_name=solver)

    x = m.add_var(var_type=INTEGER, lb=0, ub=2 * val)
    y = m.add_var(var_type=INTEGER, lb=val, ub=2 * val)
    m.objective = maximize(x - y)
    m.optimize()
    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == val
    assert round(x.x) == 2 * val
    assert round(y.x) == val
示例#12
0
def random_knapsack(n: int, interval):
    I = range(n)
    p = [randrange(*interval) for _ in I]
    w = [randrange(*interval) for _ in I]
    c = round(sum(interval) / 2 * n)

    m = Model("random-knapsack")
    x = [m.add_var(var_type=BINARY) for i in I]
    m.objective = maximize(xsum(p[i] * x[i] for i in I))
    m += xsum(w[i] * x[i] for i in I) <= c
    start = monotonic()
    print(m.optimize())
    print(f"DURATION: {(monotonic() - start) * 1000} ms")
示例#13
0
def solve_model(model, varrange, state_values, min_frames=True, output=True, relaxation=False):
    size = len(varrange)
    max_damage = 0
    min_r_frames = 0
    min_d_frames = 0
    dps = 0
    solution = {
        'dataTable' : [],
        'decisionVariables' : []
    }
    # testpath = os.getcwd() + '/lptemplates/lpfiles/TESTING.lp'
    model.objective = mip.maximize(mip.xsum(state_values['damage'][i]*varrange[i] for i in range(size)))
    # model.write(testpath) # a test file for debugging
    if not output:
        model.verbose = 0
    model.optimize(relax=relaxation) # right here is where you'd change model properties for speed
    print(model.status)
    if model.status not in [mip.OptimizationStatus.OPTIMAL]:
        solution['dataTable'].append({'id' : 'status', 'value' : 'INFEASIBLE'})
        solution['decisionVariables'].append({'id' : 'N/A', 'value' : 'N/A'})
        return solution
    max_damage = model.objective_value
    if min_frames:
        model += mip.xsum(state_values['damage'][i]*varrange[i] for i in range(size)) == max_damage
        model.objective = mip.minimize(mip.xsum(state_values['realframes'][i]*varrange[i] for i in range(size)))
        model.optimize(relax=relaxation)
    for i in range(size):
        if abs(varrange[i].x) > 1e-6: # only non-zeros
            if 'Dummy' in varrange[i].name:
                continue 
            solution['decisionVariables'].append({'id' : [varrange[i].name], 'value' : varrange[i].x})
            min_r_frames += varrange[i].x*state_values['realframes'][i]
            min_d_frames += varrange[i].x*state_values['frames'][i]
    if min_r_frames <= 0:
        dps = 0
    else:
        dps = round((60*max_damage/min_r_frames), 2)

    solution['dataTable'].append({'id' : 'Max Damage', 'value' : max_damage})
    solution['dataTable'].append({'id' : 'DPS', 'value' : dps})
    solution['dataTable'].append({'id' : 'Dragon Time', 'value' : min_d_frames})
    solution['dataTable'].append({'id' : 'Real Time', 'value' : min_r_frames})
    if output:
        print('solution:')
        for v in model.vars:
            if abs(v.x) > 1e-6: # only printing non-zeros
                print('{} : {}'.format(v.name, v.x))
        print(model.status)
        for statistic in solution['dataTable']:
            print('{:11} : {:10}'.format(statistic['id'], statistic['value']))
    return solution
def do_matching_double_matches(graph, wants_two_matches=None):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    if not wants_two_matches:
        wants_two_matches = {v: True for v in V}
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    model = Model("Allow double matches based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]

    is_best = {e: model.add_var(var_type=BINARY) for e in undirected.keys()}
    penalty = {v: model.add_var(var_type=BINARY) for v in V}
    happiness = {v: model.add_var() for v in V}

    epsilon = .0000001
    C = 1e3

    for v in V:
        model += xsum(edge_vars[s, t] for s, t in E
                      if v in [s, t]) <= 1 + penalty[v] * wants_two_matches[v]
        model += happiness[v] <= xsum(edge_vars[s, t]
                                      for s, t in E if v in [s, t]) * C
        if outputs[v]:
            model += xsum(is_best[(v, m)] for m in outputs[v]) == 1
            for m in outputs[v]:
                model += happiness[v] <= undirected[(v, m)] * weights[
                    (v, m)] + (1 - is_best[(v, m)]) * C
        else:
            happiness[v] <= 0
    model.objective = maximize(
        xsum(happiness[v] for v in V) - epsilon * xsum(penalty[v] for v in V))
    model.optimize(max_seconds=300)

    return sorted([e for e in E if edge_vars[e].x > .01])
示例#15
0
def create_mip(solver, J, dur, S, c, r, EST, relax=False, sense=MINIMIZE):
    """Creates a mip model to solve the RCPSP"""
    NR = len(c)
    mip = Model(solver_name=solver)
    sd = sum(dur[j] for j in J)
    vt = CONTINUOUS if relax else BINARY
    x = [
        {
            t: mip.add_var("x(%d,%d)" % (j, t), var_type=vt)
            for t in range(EST[j], sd + 1)
        }
        for j in J
    ]
    TJ = [set(x[j].keys()) for j in J]
    T = set()
    for j in J:
        T = T.union(TJ[j])

    if sense == MINIMIZE:
        mip.objective = minimize(xsum(t * x[J[-1]][t] for t in TJ[-1]))
    else:
        mip.objective = maximize(xsum(t * x[J[-1]][t] for t in TJ[-1]))

    # one time per job
    for j in J:
        mip += xsum(x[j][t] for t in TJ[j]) == 1, "selTime(%d)" % j

    # precedences
    for (u, v) in S:
        mip += (
            xsum(t * x[v][t] for t in TJ[v])
            >= xsum(t * x[u][t] for t in TJ[u]) + dur[u],
            "prec(%d,%d)" % (u, v),
        )

    # resource usage
    for t in T:
        for ir in range(NR):
            mip += (
                xsum(
                    r[ir][j] * x[j][tl]
                    for j in J[1:-1]
                    for tl in TJ[j].intersection(
                        set(range(t - dur[j] + 1, t + 1))
                    )
                )
                <= c[ir],
                "resUsage(%d,%d)" % (ir, t),
            )

    return mip
示例#16
0
def test_float(solver: str, val: int):
    m = Model("bounds", solver_name=solver)
    x = m.add_var(lb=0, ub=2 * val)
    y = m.add_var(lb=val, ub=2 * val)
    obj = x - y
    # No solution yet. __float__ MUST return a float type, so it returns nan.
    assert obj.x is None
    assert math.isnan(float(obj))
    m.objective = maximize(obj)
    m.optimize()
    assert m.status == OptimizationStatus.OPTIMAL
    # test vars.
    assert x.x == float(x)
    assert y.x == float(y)
    # test linear expressions.
    assert float(x + y) == (x + y).x
示例#17
0
def optimize_player_strategy(player_cards: List[int],
                             opponent_cards: List[int],
                             payoff_matrix: Matrix) -> Strategy:
    """
    Get the optimal strategy for the player, by solving
    a simple linear program based on payoff matrix.
    """
    lp = mip.Model("player_strategy", solver_name=mip.CBC)
    lp.verbose = False  # the problems are simple and we don't need to see the output

    x = [
        lp.add_var(f"x_{card}", var_type=mip.CONTINUOUS)
        for card in player_cards
    ]
    v = lp.add_var("v", var_type=mip.CONTINUOUS, lb=-mip.INF)

    for opponent_card in opponent_cards:
        transposed_row = [
            payoff_matrix[(player_card, opponent_card)]
            for player_card in player_cards
        ]
        constraint = (mip.xsum(transposed_row[i] * x_i
                               for i, x_i in enumerate(x)) - v >= 0)
        lp += constraint, f"strategy_against_{opponent_card}"
        logging.debug(f"constraint={constraint}")

    lp += mip.xsum(x) == 1, "probability_distribution"
    lp.objective = mip.maximize(v)

    # all variables are continuous so we only need to solve relaxed problem
    lp.optimize(max_seconds=30, relax=True)
    if lp.status is not mip.OptimizationStatus.OPTIMAL:
        logging.error(f"lp.status={lp.status}")
        raise RuntimeError(
            f"Solver couldn't optimize the problem and returned status {lp.status}"
        )

    strategy = Strategy(
        card_probabilities={
            card: lp.var_by_name(f"x_{card}").x
            for card in player_cards
        },
        expected_value=lp.var_by_name("v").x,
    )
    logging.debug(f"strategy.expected_value={strategy.expected_value}")
    logging.debug("\n")
    return strategy
def do_matching_two_round(graph):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    model = Model("Rogue Couples based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]
    second_vars = {e: model.add_var(var_type=BINARY) for e in E}
    partners = dict()
    second_round_partners = dict()
    for v in V:
        partners[v] = model.add_var()
        model += partners[v] == xsum(edge_vars[s, t] for s, t in E
                                     if v in [s, t])
        model += partners[v] <= 1
    for v in V:
        second_round_partners[v] = model.add_var()
        model += second_round_partners[v] == xsum(second_vars[s, t]
                                                  for s, t in E if v in [s, t])
        model += second_round_partners[v] <= 1
    for e in E:
        u, v = e
        model += second_vars[(u, v)] <= 2 - partners[v] - partners[u]

    model.objective = maximize(
        xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) *
             (edge_vars[edge] + second_vars[edge]) for edge in E))
    model.optimize(max_seconds=1000)
    return sorted([e for e in E if edge_vars[e].x > .01] +
                  [e for e in E if second_vars[e].x > .01])
示例#19
0
def Int_Knapsack(f,d, V_d, Kf):
	p = list(np.ones((len(V_d),),dtype=int))
	m = Model("knapsack")
	#x = [m.add_var(var_type=BINARY) for i in list(V_d.keys())]
	x = [(i,m.add_var(var_type=BINARY)) for i in list(V_d.keys())]
	m.objective = maximize(xsum(p[i] * x[i][1] for i in range(len(x))))
	m += xsum(V_d[x[i][0]] * x[i][1] for i in range(len(x))) <= Kf[f]
	m.optimize()
	#selected = [i for i in list(V_d.keys()) if x[i].x >= 0.99]
	selected = [x[i][0] for i in range(len(x)) if x[i][1].x >= 0.99]
	#print("selected items: {}".format(selected))
	y=(d,selected,f)
	return y



#sol = Int_Knapsack(f,d,V_d, Kf)
示例#20
0
def max_utilitarian_welfare_allocation(utilities: Dict[int, List[float]],
                                       m: Model) -> None:
    """
    Computes (one of) the item allocation(s) which maximizes utilitarian welfare, returning the optimized model.

    :param utilities: the dictionary representing the utility profile, where each key is an agent and its value an array
    of floats such that the i-th float is the utility of the i-th item for the key-agent.
    :param m: the MIP model which represents the integer linear program.
    """
    agents, items = len(utilities), len(list(utilities.values())[0])

    m.objective = maximize(
        xsum(utilities[agent][item] *
             m.var_by_name('assign_{}_{}'.format(item, agent))
             for item in range(items) for agent in range(agents)))

    m.optimize()
示例#21
0
    def set_opt_model_func(model, profile, in_committee, committeesize):
        # utility[(voter, x)] contains (intended binary) variables counting the number of approved
        # candidates in the selected committee by `voter`. This utility[(voter, x)] is true for
        # exactly the number of candidates in the committee approved by `voter` for all
        # x = 1...committeesize.

        utility = {}
        iteration = len(satisfaction_constraints)
        marginal_scorefcts = [
            scores.get_marginal_scorefct(f"atleast{i + 1}")
            for i in range(iteration + 1)
        ]

        max_in_committee = {}
        for i, voter in enumerate(profile):
            # maximum number of approved candidates that this voter can have in a committee
            max_in_committee[voter] = min(len(voter.approved), committeesize)
            for x in range(1, max_in_committee[voter] + 1):
                utility[(voter, x)] = model.add_var(var_type=mip.BINARY,
                                                    name=f"utility({i},{x})")

        # constraint: the committee has the required size
        model += mip.xsum(in_committee) == committeesize

        # constraint: utilities are consistent with actual committee
        for voter in profile:
            model += mip.xsum(
                utility[voter, x]
                for x in range(1, max_in_committee[voter] + 1)) == mip.xsum(
                    in_committee[cand] for cand in voter.approved)

        # additional constraints from previous iterations
        for prev_iteration in range(iteration):
            model += (mip.xsum(
                float(marginal_scorefcts[prev_iteration](x)) * voter.weight *
                utility[(voter, x)] for voter in profile
                for x in range(1, max_in_committee[voter] + 1)) >=
                      satisfaction_constraints[prev_iteration] - ACCURACY)

        # objective: the at-least-y score of the committee in iteration y
        model.objective = mip.maximize(
            mip.xsum(
                float(marginal_scorefcts[iteration](x)) * voter.weight *
                utility[(voter, x)] for voter in profile
                for x in range(1, max_in_committee[voter] + 1)))
示例#22
0
 def get_lineups(self, slate, ptcol, lineups, salcap=50000):
     positions = slate['positions']
     pool= pd.concat(slate['players'].values(),ignore_index='True').drop(columns='position')\
         .drop_duplicates().reset_index(drop=True)
     #Establish positions eligibility data structure
     elig = [[
         1 if plyr['name'] in list(slate['players'][pos]['name']) else 0
         for i, pos in enumerate(positions)
     ] for skip, plyr in pool.iterrows()]
     pts = list(pool[ptcol])
     #Set up player salary list
     sal = list(pool['salary'])
     #Set up range just for short reference
     I = range(len(pts))
     J = range(len(positions))
     #Set up results
     results = []
     m = Model()
     m.verbose = False
     x = [[m.add_var(var_type=BINARY) for j in J] for i in I]
     m.objective = maximize(
         xsum(x[i][j] * elig[i][j] * pts[i] for i in I for j in J))
     #Apply salary cap constraint
     m += xsum((x[i][j] * sal[i] for i in I for j in J)) <= salcap
     #Apply one player per position constraint
     for j in J:
         m += xsum(x[i][j] for i in I) == 1
     #apply max one position per player constraint
     for i in I:
         m += xsum(x[i][j] for j in J) <= 1
     for lineup in range(lineups):
         print(lineup)
         m.optimize()
         #Add lineup to results
         idx = [(i, j) for i in I for j in J if x[i][j].x >= 0.99]
         results.append(
             pd.concat([pool.iloc[i:i + 1] for i, j in idx],
                       ignore_index=True))
         results[-1]['position'] = [positions[j] for i, j in idx]
         #Apply constraint to ensure this player combination will not be repeated (cannot have three overlapping players for diversity)
         m += xsum(x[i][j] for i, skip in idx
                   for j in J) <= len(positions) - 3
     return results
示例#23
0
def ILP_optA_solution(tasks, cpu, tk, model=Model()):
    # init
    A = cpu.A
    M = cpu.M
    Sk = tk.s
    tasks = [t for t in tasks if t != tk]
    n = len(tasks)
    I = [t.W(Sk) for t in tasks]
    a = [t.a for t in tasks]
    Ak = opt(tasks, cpu, tk)

    if (n <= 0):
        return 0
    if (Ak == 0):
        Ak = A
    # Ak = A

    # model = Model()
    model.clear()
    x = {
        i: model.add_var(obj=0, var_type="C", name="x[%d]" % i)
        for i in range(n)
    }
    y = {
        i: model.add_var(obj=0, var_type="C", name="y[%d]" % i)
        for i in range(n)
    }

    model.objective = maximize(
        xsum((1 / M) * x[i] + (a[i] / Ak) * y[i] for i in range(n)))
    model.verbose = False

    for i in range(n):
        model += x[i] + y[i] <= I[i]
    for i in range(n):
        model += x[i] <= xsum((1 / M) * x[j] for j in range(n))
    for i in range(n):
        model += y[i] <= xsum((a[j] / Ak) * y[j] for j in range(n))

    model.optimize()

    return model.objective_value
示例#24
0
def maximize_sum(plfs, max_costs):
    # pylint: disable=too-many-locals
    m = Model("bid-landscapes")
    costs = LinExpr()
    objective = LinExpr()
    xs = []
    ws = []
    for (i, plf) in enumerate(plfs):
        k = len(plf)
        w = [m.add_var(var_type=CONTINUOUS) for _ in range(0, k)]
        x = [m.add_var(var_type=BINARY) for _ in range(0, k - 1)]
        xs.append(x)
        ws.append(w)

        m += xsum(w[i] for i in range(0, k)) == 1
        for i in range(0, k):
            m += w[i] >= 0

        m += w[0] <= x[0]
        for i in range(1, k - 1):
            m += w[i] <= x[i - 1] + x[i]
        m += w[k - 1] <= x[k - 2]
        m += xsum(x[k] for k in range(0, k - 1)) == 1

        for i in range(0, k):
            costs.add_term(w[i] * plf.a[i])
            objective.add_term(w[i] * plf.b[i])

    m += costs <= max_costs
    m.objective = maximize(objective)
    start = monotonic()
    print(m.optimize())
    print(f"DURATION: {(monotonic() - start) * 1000} ms")

    optimum = []
    for (i, plf) in enumerate(plfs):
        k = len(plf)
        u_i = sum(ws[i][j].x * plf.a[j] for j in range(0, k))
        v_i = sum(ws[i][j].x * plf.b[j] for j in range(0, k))
        optimum.append(Line(cost=u_i, revenue=v_i, plf=plf))
    return optimum
示例#25
0
    def set_opt_model_func(model, profile, in_committee, committeesize,
                           previously_found_committees, scorefct):
        # utility[(voter, l)] contains (intended binary) variables counting the number of approved
        # candidates in the selected committee by `voter`. This utility[(voter, l)] is true for
        # exactly the number of candidates in the committee approved by `voter` for all
        # l = 1...committeesize.
        #
        # If scorefct(l) > 0 for l >= 1, we assume that scorefct is monotonic decreasing and
        # therefore in combination with the objective function the following interpreation is
        # valid:
        # utility[(voter, l)] indicates whether `voter` approves at least l candidates in the
        # committee (this is the case for scorefct "pav", "slav" or "geom").
        utility = {}

        for i, voter in enumerate(profile):
            for l in range(1, committeesize + 1):
                utility[(voter, l)] = model.add_var(var_type=mip.BINARY,
                                                    name=f"utility-v{i}-l{l}")
                # TODO: could be faster with lb=0.0, ub=1.0, var_type=mip.CONTINUOUS

        # constraint: the committee has the required size
        model += mip.xsum(in_committee) == committeesize

        # constraint: utilities are consistent with actual committee
        for voter in profile:
            model += mip.xsum(
                utility[voter, l]
                for l in range(1, committeesize + 1)) == mip.xsum(
                    in_committee[cand] for cand in voter.approved)

        # find a new committee that has not been found yet by excluding previously found committees
        for committee in previously_found_committees:
            model += mip.xsum(in_committee[cand]
                              for cand in committee) <= committeesize - 1

        # objective: the PAV score of the committee
        model.objective = mip.maximize(
            mip.xsum(
                float(scorefct(l)) * voter.weight * utility[(voter, l)]
                for voter in profile for l in range(1, committeesize + 1)))
示例#26
0
    def set_opt_model_func(model, profile, in_committee, committeesize,
                           previously_found_committees, scorefct):
        load = {}
        for cand in profile.candidates:
            for voter in profile:
                load[(voter, cand)] = model.add_var(lb=0.0,
                                                    ub=1.0,
                                                    var_type=mip.CONTINUOUS)

        # constraint: the committee has the required size
        model += mip.xsum(in_committee[cand]
                          for cand in profile.candidates) == committeesize

        for cand in profile.candidates:
            for voter in profile:
                if cand not in voter.approved:
                    load[(voter, cand)] = 0

        # a candidate's load is distributed among his approvers
        for cand in profile.candidates:
            model += (mip.xsum(
                voter.weight * load[(voter, cand)] for voter in profile
                if cand in profile.candidates) >= in_committee[cand])

        # find a new committee that has not been found before
        for committee in previously_found_committees:
            model += mip.xsum(in_committee[cand]
                              for cand in committee) <= committeesize - 1

        loadbound = model.add_var(lb=0,
                                  ub=committeesize,
                                  var_type=mip.CONTINUOUS,
                                  name="loadbound")
        for voter in profile:
            model += mip.xsum(load[(voter, cand)]
                              for cand in voter.approved) <= loadbound

        # maximizing the negative distance makes code more similar to the other methods here
        model.objective = mip.maximize(-loadbound)
示例#27
0
def solve_it_mip(input_data):
    from mip import Model, xsum, maximize, BINARY

    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])
    I = range(item_count)
    knapsack = [0] * item_count

    values = [0] * item_count
    weights = [0] * item_count

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

    m = Model("knapsack")

    x = [m.add_var(var_type=BINARY) for i in I]

    m.objective = maximize(xsum(values[i] * x[i] for i in I))

    m += xsum(weights[i] * x[i] for i in I) <= capacity

    m.verbose = 0
    #m.emphasis = 1
    status = m.optimize()

    selected = [i for i in I if x[i].x >= 0.99]
    for index in selected:
        knapsack[index] = knapsack[index] + 1
    output_data = f"{int(m.objective_value)} {1}\n" + " ".join(
        map(str, knapsack))
    return output_data
示例#28
0
def test_knapsack(solver: str):
    p = [10, 13, 18, 31, 7, 15]
    w = [11, 15, 20, 35, 10, 33]
    c, I = 47, range(len(w))

    m = Model('knapsack', solver_name=solver)

    x = [m.add_var(var_type=BINARY) for i in I]

    m.objective = maximize(xsum(p[i] * x[i] for i in I))

    m += xsum(w[i] * x[i] for i in I) <= c, 'cap'

    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == 41

    m.constr_by_name('cap').rhs = 60
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert round(m.objective_value) == 51
示例#29
0
    def set_opt_model_func(model, profile, in_committee, committeesize):
        # utility[(voter, x)] contains (intended binary) variables counting the number of approved
        # candidates in the selected committee by `voter`. This utility[(voter, x)] is true for
        # exactly the number of candidates in the committee approved by `voter` for all
        # x = 1...committeesize.
        #
        # If marginal_scorefct(x) > 0 for x >= 1, we assume that marginal_scorefct is monotonic
        # decreasing and therefore in combination with the objective function the following
        # interpreation is valid:
        # utility[(voter, x)] indicates whether `voter` approves at least x candidates in the
        # committee (this is the case for marginal_scorefct "pav", "slav" or "geom").
        utility = {}

        max_in_committee = {}
        for i, voter in enumerate(profile):
            max_in_committee[voter] = min(len(voter.approved), committeesize)
            for x in range(1, max_in_committee[voter] + 1):
                utility[(voter, x)] = model.add_var(var_type=mip.BINARY,
                                                    name=f"utility({i},{x})")

        # constraint: the committee has the required size
        model += mip.xsum(in_committee) == committeesize

        # constraint: utilities are consistent with actual committee
        for voter in profile:
            model += mip.xsum(
                utility[voter, x]
                for x in range(1, max_in_committee[voter] + 1)) == mip.xsum(
                    in_committee[cand] for cand in voter.approved)

        # objective: the Thiele score of the committee
        model.objective = mip.maximize(
            mip.xsum(
                float(marginal_scorefct(x)) * voter.weight *
                utility[(voter, x)] for voter in profile
                for x in range(1, max_in_committee[voter] + 1)))
示例#30
0
Groups = set(range(GROUP_COUNT))
People = set(range(len(people)))
Voices = set(range(4))

model = Model("Optimizing Choir Groups")
X = [[model.add_var(var_type=BINARY) for g in Groups] for p in People]
A = [[[model.add_var(var_type=BINARY) for g in Groups] for p1 in People]
     for p2 in People]

# objective function
# scaling wishes with 1/sqrt(#wishes)
#model.objective = maximize(xsum(L[p1][p2] * A[p1][p2][g]/math.sqrt(sum(L[p1])+1) for p1 in People for p2 in People for g in Groups))
# scaling wishes with 1/(#wishes)
model.objective = maximize(
    xsum(L[p1][p2] * A[p1][p2][g] / max(sum(L[p1]), 1) for p1 in People
         for p2 in People for g in Groups))
# scaling wishes with 1
#model.objective = maximize(xsum(L[p1][p2] * A[p1][p2][g] for p1 in People for p2 in People for g in Groups))

# constraint defining A[p1][p2][g] = X[p1][g]*X[p2][g]
for p1 in People:
    for p2 in People:
        for g in Groups:
            model += A[p1][p2][g] <= X[p1][g]
            model += A[p1][p2][g] <= X[p2][g]

# constraints on group size
for g in Groups:
    model += xsum(X[p][g] for p in People) <= MAX_GROUP_SIZE