```json
{
  "sym_variables": [
    ("x0", "hours worked by Bobby"),
    ("x1", "hours worked by Dale"),
    ("x2", "hours worked by Paul"),
    ("x3", "hours worked by John")
  ],
  "objective_function": "2*x0 + 5*x1 + 7*x2 + 3*x3",
  "constraints": [
    "2*x0 + 5*x3 >= 20",
    "3*x2 + 5*x3 >= 16",
    "2*x0 + 5*x1 + 3*x2 + 5*x3 >= 16",
    "3*x1 + 2*x2 >= 22",
    "3*x1 + 5*x3 >= 29",
    "2*x0 + 5*x3 >= 29",
    "2*x0 + 2*x2 >= 29",
    "2*x0 + 3*x1 + 2*x2 + 5*x3 >= 29",
    "4*x0 + 5*x2 >= 8",
    "4*x0 + 3*x1 >= 7",
    "3*x1 + 2*x3 >= 9",
    "4*x0 + 3*x1 + 5*x2 >= 6",
    "3*x1 + 5*x2 + 2*x3 >= 6",
    "4*x0 + 3*x1 + 5*x2 >= 5",
    "3*x1 + 5*x2 + 2*x3 >= 5",
    "4*x0 + 3*x1 + 5*x2 + 2*x3 >= 5",
    "4*x0 + 2*x1 >= 17",
    "2*x1 + 4*x3 >= 17",
    "4*x0 + 2*x1 + 4*x2 + 4*x3 >= 17",
    "4*x0 + 1*x2 >= 6",
    "1*x2 + 1*x3 >= 9",
    "1*x1 + 1*x2 >= 12",
    "1*x1 + 1*x3 >= 14",
    "4*x0 + 1*x1 >= 5",
    "4*x0 + 1*x1 + 1*x2 >= 8",
    "4*x0 + 1*x1 + 1*x3 >= 8",
    "1*x1 + 1*x2 + 1*x3 >= 8",
    "4*x0 + 1*x1 + 1*x2 >= 11",
    "4*x0 + 1*x1 + 1*x3 >= 11",
    "1*x1 + 1*x2 + 1*x3 >= 11",
    "4*x0 + 1*x1 + 1*x2 >= 16",
    "4*x0 + 1*x1 + 1*x3 >= 16",
    "1*x1 + 1*x2 + 1*x3 >= 16",
    "4*x0 + 1*x1 + 1*x2 + 1*x3 >= 16",
    "5*x1 + 3*x2 <= 69",
    "2*x0 + 5*x3 <= 87",
    "5*x1 + 3*x2 + 5*x3 <= 24",
    "2*x0 + 5*x1 + 3*x2 <= 39",
    "2*x0 + 5*x1 + 5*x3 <= 64",
    "3*x1 + 2*x2 <= 36",
    "2*x0 + 2*x2 <= 71",
    "2*x0 + 2*x2 + 5*x3 <= 105",
    "3*x1 + 2*x2 + 5*x3 <= 83",
    "2*x0 + 3*x1 + 5*x3 <= 85",
    "2*x0 + 3*x1 + 2*x2 <= 47",
    "4*x0 + 3*x1 <= 13",
    "4*x0 + 5*x2 + 2*x3 <= 42",
    "4*x0 + 3*x1 + 5*x2 <= 11",
    "4*x0 + 2*x1 <= 79",
    "1*x1 + 1*x2 <= 48",
    "4*x0 + 1*x2 <= 28"
  ]
}
```

```python
from gurobipy import Model, GRB

# Create a new model
m = Model("optimization_problem")

# Create variables
bobby = m.addVar(vtype=GRB.CONTINUOUS, name="bobby")
dale = m.addVar(vtype=GRB.CONTINUOUS, name="dale")
paul = m.addVar(vtype=GRB.INTEGER, name="paul")
john = m.addVar(vtype=GRB.INTEGER, name="john")


# Set objective function
m.setObjective(2*bobby + 5*dale + 7*paul + 3*john, GRB.MINIMIZE)

# Add constraints
m.addConstr(2*bobby + 5*john >= 20)
m.addConstr(3*paul + 5*john >= 16)
m.addConstr(2*bobby + 5*dale + 3*paul + 5*john >= 16)
m.addConstr(3*dale + 2*paul >= 22)
m.addConstr(3*dale + 5*john >= 29)
m.addConstr(2*bobby + 5*john >= 29)
m.addConstr(2*bobby + 2*paul >= 29)
m.addConstr(2*bobby + 3*dale + 2*paul + 5*john >= 29)
m.addConstr(4*bobby + 5*paul >= 8)
m.addConstr(4*bobby + 3*dale >= 7)
m.addConstr(3*dale + 2*john >= 9)
m.addConstr(4*bobby + 3*dale + 5*paul >= 6)
m.addConstr(3*dale + 5*paul + 2*john >= 6)
m.addConstr(4*bobby + 3*dale + 5*paul >= 5)
m.addConstr(3*dale + 5*paul + 2*john >= 5)
m.addConstr(4*bobby + 3*dale + 5*paul + 2*john >= 5)
m.addConstr(4*bobby + 2*dale >= 17)
m.addConstr(2*dale + 4*john >= 17)
m.addConstr(4*bobby + 2*dale + 4*paul + 4*john >= 17)
m.addConstr(4*bobby + paul >= 6)
m.addConstr(paul + john >= 9)
m.addConstr(dale + paul >= 12)
m.addConstr(dale + john >= 14)
m.addConstr(4*bobby + dale >= 5)
m.addConstr(4*bobby + dale + paul >= 8)
m.addConstr(4*bobby + dale + john >= 8)
m.addConstr(dale + paul + john >= 8)
m.addConstr(4*bobby + dale + paul >= 11)
m.addConstr(4*bobby + dale + john >= 11)
m.addConstr(dale + paul + john >= 11)
m.addConstr(4*bobby + dale + paul >= 16)
m.addConstr(4*bobby + dale + john >= 16)
m.addConstr(dale + paul + john >= 16)
m.addConstr(4*bobby + dale + paul + john >= 16)
m.addConstr(5*dale + 3*paul <= 69)
m.addConstr(2*bobby + 5*john <= 87)
m.addConstr(5*dale + 3*paul + 5*john <= 24)
m.addConstr(2*bobby + 5*dale + 3*paul <= 39)
m.addConstr(2*bobby + 5*dale + 5*john <= 64)
m.addConstr(3*dale + 2*paul <= 36)
m.addConstr(2*bobby + 2*paul <= 71)
m.addConstr(2*bobby + 2*paul + 5*john <= 105)
m.addConstr(3*dale + 2*paul + 5*john <= 83)
m.addConstr(2*bobby + 3*dale + 5*john <= 85)
m.addConstr(2*bobby + 3*dale + 2*paul <= 47)
m.addConstr(4*bobby + 3*dale <= 13)
m.addConstr(4*bobby + 5*paul + 2*john <= 42)
m.addConstr(4*bobby + 3*dale + 5*paul <= 11)
m.addConstr(4*bobby + 2*dale <= 79)
m.addConstr(dale + paul <= 48)
m.addConstr(4*bobby + paul <= 28)



# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))
else:
    print("Infeasible")

```
