To solve the optimization problem described, we first need to translate the natural language description into a symbolic representation. This involves identifying variables and constraints based on the given information.

Let's denote:
- $x_1$ as 'hours worked by George',
- $x_2$ as 'hours worked by Paul',
- $x_3$ as 'hours worked by Peggy'.

The objective function to minimize is: $5x_1 + 6x_2 + 5x_3$.

Given constraints:
1. $(2.1)x_1 + (1.32)x_3 \geq 21$
2. $(5.73)x_2 + (1.32)x_3 \geq 18$
3. $(2.1)x_1 + (5.73)x_2 + (1.32)x_3 \geq 14$
4. The same as constraint 3, so we consider it only once.
5. $-10x_2 + 6x_3 \geq 0$
6. $9x_1 - 4x_2 \geq 0$
7. $(2.1)x_1 + (5.73)x_2 \leq 59$
8. $(5.73)x_2 + (1.32)x_3 \leq 31$

Since George's hours cannot be fractional, $x_1$ is an integer variable. Paul and Peggy can have fractional hours worked, so $x_2$ and $x_3$ are continuous variables.

The symbolic representation of the problem in JSON format is:
```json
{
    'sym_variables': [('x1', 'hours worked by George'), ('x2', 'hours worked by Paul'), ('x3', 'hours worked by Peggy')],
    'objective_function': '5*x1 + 6*x2 + 5*x3',
    'constraints': [
        '(2.1)*x1 + (1.32)*x3 >= 21',
        '(5.73)*x2 + (1.32)*x3 >= 18',
        '(2.1)*x1 + (5.73)*x2 + (1.32)*x3 >= 14',
        '-10*x2 + 6*x3 >= 0',
        '9*x1 - 4*x2 >= 0',
        '(2.1)*x1 + (5.73)*x2 <= 59',
        '(5.73)*x2 + (1.32)*x3 <= 31'
    ]
}
```

Now, let's implement this optimization problem using Gurobi Python API:
```python
from gurobipy import *

# Create a model
m = Model("Optimization_Problem")

# Define variables
x1 = m.addVar(vtype=GRB.INTEGER, name="hours_worked_by_George")
x2 = m.addVar(vtype=GRB.CONTINUOUS, name="hours_worked_by_Paul")
x3 = m.addVar(vtype=GRB.CONTINUOUS, name="hours_worked_by_Peggy")

# Define the objective function
m.setObjective(5*x1 + 6*x2 + 5*x3, GRB.MINIMIZE)

# Add constraints
m.addConstr((2.1)*x1 + (1.32)*x3 >= 21, name="constraint_1")
m.addConstr((5.73)*x2 + (1.32)*x3 >= 18, name="constraint_2")
m.addConstr((2.1)*x1 + (5.73)*x2 + (1.32)*x3 >= 14, name="constraint_3")
m.addConstr(-10*x2 + 6*x3 >= 0, name="constraint_4")
m.addConstr(9*x1 - 4*x2 >= 0, name="constraint_5")
m.addConstr((2.1)*x1 + (5.73)*x2 <= 59, name="constraint_6")
m.addConstr((5.73)*x2 + (1.32)*x3 <= 31, name="constraint_7")

# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Hours worked by George: {x1.x}")
    print(f"Hours worked by Paul: {x2.x}")
    print(f"Hours worked by Peggy: {x3.x}")
    print(f"Objective function value: {m.objVal}")
else:
    print("No optimal solution found")
```