import argparse
from gurobipy import Model, GRB, quicksum


def maximize_min_value(i, m, upper_bound, target_sum):
    model = Model("maximize_min_value")
    U = upper_bound

    # Entscheidungsvariablen
    x = model.addVars(i, vtype=GRB.INTEGER, name="x")
    b = model.addVars(i, vtype=GRB.BINARY, name="b")
    L = model.addVar(vtype=GRB.INTEGER, name="L")

    # Zielfunktion
    model.setObjective(L, GRB.MAXIMIZE)

    # Nebenbedingungen
    model.addConstr(quicksum(x[j] for j in range(i)) == target_sum, name="sum_constraint")
    for j in range(i):
        # U is a valid Big-M constant; here we may choose U = upper_bound.
        model.addConstr(L <= x[j] + U * (1 - b[j]), name=f"min_constraint_{j}")
        model.addConstr(x[j] <= upper_bound * b[j], name=f"max_constraint_{j}")
        model.addConstr(x[j] >= m * b[j], name=f"min_bound_constraint_{j}")

    model.optimize()

    # Ergebnis ausgeben
    if model.status == GRB.OPTIMAL:
        solution = [x[j].x for j in range(i) if b[j].x > 0.5]
        print("Optimale Lösung gefunden:")
        print(f"Verwendete Zahlen: {solution}")
        print(f"Minimaler Wert (L): {L.x}")
    else:
        print("Keine optimale Lösung gefunden")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Maximize the minimum value of a subset that sums to a target.')
    parser.add_argument('i', type=int, help='number of variables')
    parser.add_argument('m', type=int, help='minimum value for variables')
    parser.add_argument('M', type=int, help='maximum value for variables')
    parser.add_argument('target_sum', type=int, help='the target sum')
    
    args = parser.parse_args()
    maximize_min_value(args.i, args.m, args.M, args.target_sum)
