Here's the Gurobi code to solve the optimization problem:

```python
import gurobipy as gp

# Create a new model
m = gp.Model("WorkOptimization")

# Create variables
bobby_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="bobby_hours")
bill_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="bill_hours")
mary_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="mary_hours")
peggy_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="peggy_hours")

# Set objective function
m.setObjective(7.25 * bobby_hours + 6.29 * bill_hours + 1.38 * mary_hours + 5.76 * peggy_hours, gp.GRB.MINIMIZE)

# Resource data
resources = {
    'r0': {'upper_bound': 556, 'x0': 20, 'x1': 24, 'x2': 4, 'x3': 25},
    'r1': {'upper_bound': 305, 'x0': 2, 'x1': 1, 'x2': 22, 'x3': 21},
    'r2': {'upper_bound': 377, 'x0': 8, 'x1': 26, 'x2': 2, 'x3': 18},
    'r3': {'upper_bound': 557, 'x0': 18, 'x1': 29, 'x2': 23, 'x3': 4}
}

# Add constraints
m.addConstr(4 * mary_hours + 25 * peggy_hours >= 59)
m.addConstr(20 * bobby_hours + 4 * mary_hours >= 59)
m.addConstr(24 * bill_hours + 25 * peggy_hours >= 95)
m.addConstr(20 * bobby_hours + 24 * bill_hours >= 95)
m.addConstr(24 * bill_hours + 4 * mary_hours + 25 * peggy_hours >= 116)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 4 * mary_hours >= 116)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 25 * peggy_hours >= 116)
m.addConstr(24 * bill_hours + 4 * mary_hours + 25 * peggy_hours >= 81)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 4 * mary_hours >= 81)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 25 * peggy_hours >= 81)
m.addConstr(24 * bill_hours + 4 * mary_hours + 25 * peggy_hours >= 70)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 4 * mary_hours >= 70)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 25 * peggy_hours >= 70)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 4 * mary_hours + 25 * peggy_hours >= 70)

m.addConstr(1 * bill_hours + 22 * mary_hours >= 72)
m.addConstr(22 * mary_hours + 21 * peggy_hours >= 25)
m.addConstr(2 * bobby_hours + 1 * bill_hours >= 32)
m.addConstr(2 * bobby_hours + 21 * peggy_hours >= 69)
m.addConstr(2 * bobby_hours + 22 * mary_hours >= 48)
m.addConstr(2 * bobby_hours + 1 * bill_hours + 21 * peggy_hours >= 51)
m.addConstr(2 * bobby_hours + 1 * bill_hours + 22 * mary_hours + 21 * peggy_hours >= 51)

m.addConstr(8 * bobby_hours + 2 * mary_hours >= 56)
m.addConstr(26 * bill_hours + 2 * mary_hours >= 82)
m.addConstr(8 * bobby_hours + 26 * bill_hours >= 56)
m.addConstr(8 * bobby_hours + 2 * mary_hours + 18 * peggy_hours >= 68)
m.addConstr(8 * bobby_hours + 26 * bill_hours + 2 * mary_hours >= 68)
m.addConstr(8 * bobby_hours + 2 * mary_hours + 18 * peggy_hours >= 64)
m.addConstr(8 * bobby_hours + 26 * bill_hours + 2 * mary_hours >= 64)
m.addConstr(8 * bobby_hours + 26 * bill_hours + 2 * mary_hours + 18 * peggy_hours >= 64)


m.addConstr(23 * mary_hours + 4 * peggy_hours >= 94)
m.addConstr(18 * bobby_hours + 23 * mary_hours + 4 * peggy_hours >= 121)
m.addConstr(18 * bobby_hours + 29 * bill_hours + 23 * mary_hours >= 121)
m.addConstr(29 * bill_hours + 23 * mary_hours + 4 * peggy_hours >= 121)
m.addConstr(18 * bobby_hours + 23 * mary_hours + 4 * peggy_hours >= 130)
m.addConstr(18 * bobby_hours + 29 * bill_hours + 23 * mary_hours >= 130)
m.addConstr(29 * bill_hours + 23 * mary_hours + 4 * peggy_hours >= 130)
m.addConstr(18 * bobby_hours + 23 * mary_hours + 4 * peggy_hours >= 125)
m.addConstr(18 * bobby_hours + 29 * bill_hours + 23 * mary_hours >= 125)
m.addConstr(29 * bill_hours + 23 * mary_hours + 4 * peggy_hours >= 125)
m.addConstr(18 * bobby_hours + 29 * bill_hours + 23 * mary_hours + 4 * peggy_hours >= 125)


m.addConstr(5 * bobby_hours - mary_hours >= 0)
m.addConstr(-5 * bill_hours + 3 * peggy_hours >= 0)

m.addConstr(20 * bobby_hours + 25 * peggy_hours <= 353)
m.addConstr(20 * bobby_hours + 24 * bill_hours <= 497)
m.addConstr(20 * bobby_hours + 4 * mary_hours <= 476)
m.addConstr(24 * bill_hours + 4 * mary_hours <= 502)
m.addConstr(20 * bobby_hours + 24 * bill_hours + 4 * mary_hours <= 317)
m.addConstr(20 * bobby_hours + 4 * mary_hours + 25 * peggy_hours <= 548)

m.addConstr(22 * mary_hours + 21 * peggy_hours <= 169)
m.addConstr(1 * bill_hours + 21 * peggy_hours <= 106)
m.addConstr(1 * bill_hours + 22 * mary_hours + 21 * peggy_hours <= 130)
m.addConstr(2 * bobby_hours + 22 * mary_hours + 21 * peggy_hours <= 101)

m.addConstr(26 * bill_hours + 18 * peggy_hours <= 115)
m.addConstr(2 * mary_hours + 18 * peggy_hours <= 227)
m.addConstr(8 * bobby_hours + 2 * mary_hours + 18 * peggy_hours <= 295)

m.addConstr(29 * bill_hours + 23 * mary_hours + 4 * peggy_hours <= 345)
m.addConstr(18 * bobby_hours + 29 * bill_hours + 4 * peggy_hours <= 548)



# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Optimal solution found')
    print('Objective value:', m.objVal)
    for v in m.getVars():
        print(f'{v.varName}: {v.x}')
elif m.status == gp.GRB.INFEASIBLE:
    print('Model is infeasible')
else:
    print(f'Optimization ended with status {m.status}')

```
