# Complete GUROBIPY implementation - Retry Attempt 2

import gurobipy as gp
from gurobipy import GRB

def optimize_bank_funds():
    # 1. MODEL & DATA SETUP
    model = gp.Model("small_bank_1")
    
    # Data from the problem statement
    savings_interest_rates = [0.012, 0.015, 0.018]
    checking_interest_rates = [0.006, 0.008, 0.01]
    total_funds = [5000.0, 10000.0, 15000.0]
    min_savings_balance = [1000.0, 2000.0, 3000.0]  # Assumed minimum balances
    min_checking_balance = [500.0, 1000.0, 1500.0]  # Assumed minimum balances
    
    # Validate array lengths
    n_customers = len(total_funds)
    assert len(savings_interest_rates) == len(checking_interest_rates) == n_customers, "Array length mismatch"
    assert len(min_savings_balance) == len(min_checking_balance) == n_customers, "Array length mismatch"
    
    # 2. VARIABLES
    savings = model.addVars(n_customers, vtype=GRB.CONTINUOUS, name="savings", lb=0)
    checking = model.addVars(n_customers, vtype=GRB.CONTINUOUS, name="checking", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum(savings_interest_rates[i] * savings[i] + checking_interest_rates[i] * checking[i] for i in range(n_customers)),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    # Total Funds Constraint
    model.addConstrs(
        (savings[i] + checking[i] <= total_funds[i] for i in range(n_customers)),
        name="total_funds"
    )
    
    # Minimum Savings Balance Constraint
    model.addConstrs(
        (savings[i] >= min_savings_balance[i] for i in range(n_customers)),
        name="min_savings_balance"
    )
    
    # Minimum Checking Balance Constraint
    model.addConstrs(
        (checking[i] >= min_checking_balance[i] for i in range(n_customers)),
        name="min_checking_balance"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_customers):
            print(f"Customer {i+1}: Savings = {savings[i].x:.2f}, Checking = {checking[i].x:.2f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_bank_funds()