## Problem Description and Formulation

The problem is an optimization problem where we need to maximize the objective function: $6 \times \text{hours worked by Paul} + 4 \times \text{hours worked by Hank}$, subject to various constraints.

## Constraints

The constraints can be categorized into two types: individual attribute constraints for Paul and Hank, and combined attribute constraints.

### Individual Attribute Constraints

These are already given as attributes for Paul and Hank:
- Paul's organization score: 13
- Paul's likelihood to quit index: 6
- Paul's dollar cost per hour: 6
- Paul's paperwork competence rating: 11
- Hank's organization score: 3
- Hank's likelihood to quit index: 14
- Hank's dollar cost per hour: 13
- Hank's paperwork competence rating: 11

### Combined Attribute Constraints

1. Total combined organization score $\geq 8$ and $\leq 42$ (with an upper bound of 53)
2. Total combined likelihood to quit index $\geq 29$ and $\leq 42$ (with an upper bound of 62)
3. Total combined dollar cost per hour $\geq 7$ and $\leq 38$
4. Total combined paperwork competence rating $\geq 17$ and $\leq 20$ (with an upper bound of 39)
5. $4 \times \text{hours worked by Paul} - 7 \times \text{hours worked by Hank} \geq 0$

## Gurobi Code Formulation

```python
import gurobi

def solve_optimization_problem():
    # Create a new model
    model = gurobi.Model()

    # Define variables
    hours_worked_by_paul = model.addVar(lb=0, name="hours_worked_by_paul", vtype=gurobi.GRB.CONTINUOUS)
    hours_worked_by_hank = model.addVar(lb=0, name="hours_worked_by_hank", vtype=gurobi.GRB.CONTINUOUS)

    # Objective function: Maximize 6*Paul + 4*Hank
    model.setObjective(6 * hours_worked_by_paul + 4 * hours_worked_by_hank, gurobi.GRB.MAXIMIZE)

    # Constraints
    # Individual constraints are implicitly handled through variable attributes
    # Combined constraints
    model.addConstr(13 * hours_worked_by_paul + 3 * hours_worked_by_hank >= 8, name="org_score_min")
    model.addConstr(13 * hours_worked_by_paul + 3 * hours_worked_by_hank <= 42, name="org_score_max")
    model.addConstr(6 * hours_worked_by_paul + 14 * hours_worked_by_hank >= 29, name="quit_index_min")
    model.addConstr(6 * hours_worked_by_paul + 14 * hours_worked_by_hank <= 42, name="quit_index_max")
    model.addConstr(6 * hours_worked_by_paul + 13 * hours_worked_by_hank >= 7, name="dollar_cost_min")
    model.addConstr(6 * hours_worked_by_paul + 13 * hours_worked_by_hank <= 38, name="dollar_cost_max")
    model.addConstr(11 * hours_worked_by_paul + 11 * hours_worked_by_hank >= 17, name="paperwork_min")
    model.addConstr(11 * hours_worked_by_paul + 11 * hours_worked_by_hank <= 20, name="paperwork_max")
    model.addConstr(4 * hours_worked_by_paul - 7 * hours_worked_by_hank >= 0, name="linear_constraint")

    # Solve the model
    model.optimize()

    # Print the solution
    if model.status == gurobi.GRB.OPTIMAL:
        print("Optimal Solution:")
        print(f"Hours worked by Paul: {hours_worked_by_paul.varValue}")
        print(f"Hours worked by Hank: {hours_worked_by_hank.varValue}")
        print(f"Objective: {model.objVal}")
    else:
        print("No optimal solution found.")

solve_optimization_problem()
```