#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Farm Selection Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def farm_selection_optimization():
    """Optimize farm selection to maximize quality score while respecting city constraints."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("farm_selection")
    
    # Data from the problem
    farms = [1, 2, 3]
    horses = {1: 5, 2: 10, 3: 15}
    cattle = {1: 20, 2: 30, 3: 40}
    pigs = {1: 50, 2: 60, 3: 70}
    sheep_and_goats = {1: 30, 2: 40, 3: 50}
    
    # City capacities
    max_farms = 10
    max_horses = 50
    max_cattle = 100
    max_pigs = 200
    max_sheep_goats = 150
    
    # Validate array lengths before loops
    assert len(farms) == len(horses) == len(cattle) == len(pigs) == len(sheep_and_goats), "Array length mismatch"
    
    # 2. VARIABLES
    x = {i: model.addVar(vtype=GRB.BINARY, name=f"x_{i}") for i in farms}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize the total quality score
    model.setObjective(
        gp.quicksum((0.30 * horses[i] + 0.25 * cattle[i] + 0.20 * pigs[i] + 0.25 * sheep_and_goats[i]) * x[i] for i in farms),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    # Maximum number of farms
    model.addConstr(gp.quicksum(x[i] for i in farms) <= max_farms, name="max_farms")
    
    # Maximum number of horses
    model.addConstr(gp.quicksum(horses[i] * x[i] for i in farms) <= max_horses, name="max_horses")
    
    # Maximum number of cattle
    model.addConstr(gp.quicksum(cattle[i] * x[i] for i in farms) <= max_cattle, name="max_cattle")
    
    # Maximum number of pigs
    model.addConstr(gp.quicksum(pigs[i] * x[i] for i in farms) <= max_pigs, name="max_pigs")
    
    # Maximum number of sheep and goats
    model.addConstr(gp.quicksum(sheep_and_goats[i] * x[i] for i in farms) <= max_sheep_goats, name="max_sheep_goats")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in farms:
            if x[i].x > 0.5:
                print(f"Farm {i} is invited.")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
if __name__ == "__main__":
    farm_selection_optimization()