```json
{
  "sym_variables": [
    ("x0", "milkshakes"),
    ("x1", "peanutbutter sandwiches")
  ],
  "objective_function": "1.66 * x0 + 8.63 * x1",
  "constraints": [
    "8.76 * x0 + 11.41 * x1 >= 36",
    "1 * x0 + -9 * x1 >= 0",
    "8.76 * x0 + 11.41 * x1 <= 58",
    "8.76 * x0 + 11.41 * x1 <= 58"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
milkshakes = m.addVar(vtype=gp.GRB.CONTINUOUS, name="milkshakes")
peanutbutter_sandwiches = m.addVar(vtype=gp.GRB.CONTINUOUS, name="peanutbutter_sandwiches")

# Set objective function
m.setObjective(1.66 * milkshakes + 8.63 * peanutbutter_sandwiches, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(8.76 * milkshakes + 11.41 * peanutbutter_sandwiches >= 36, "protein_lower_bound")
m.addConstr(1 * milkshakes - 9 * peanutbutter_sandwiches >= 0, "milkshake_sandwich_ratio")
m.addConstr(8.76 * milkshakes + 11.41 * peanutbutter_sandwiches <= 58, "protein_upper_bound1")
m.addConstr(8.76 * milkshakes + 11.41 * peanutbutter_sandwiches <= 58, "protein_upper_bound2")


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Milkshakes: {milkshakes.x}")
    print(f"Peanutbutter Sandwiches: {peanutbutter_sandwiches.x}")
    print(f"Objective value: {m.objVal}")
elif m.status == gp.GRB.INFEASIBLE:
    print("Model is infeasible.")
else:
    print(f"Optimization ended with status {m.status}")

```
