```json
{
  "sym_variables": [
    ("x0", "kale salads"),
    ("x1", "rotisserie chickens"),
    ("x2", "potatoes"),
    ("x3", "blueberry pies")
  ],
  "objective_function": "3*x0 + 7*x1 + 7*x2 + 5*x3",
  "constraints": [
    "8*x0 + 2*x2 >= 3",
    "2*x2 + 6*x3 >= 6",
    "8*x1 + 6*x3 >= 8",
    "8*x0 + 8*x1 >= 10",
    "8*x0 + 8*x1 + 2*x2 + 6*x3 >= 10",
    "7*x0 + 7*x2 >= 10",
    "2*x1 + 2*x3 >= 18",
    "2*x1 + 7*x2 >= 9",
    "7*x0 + 2*x3 >= 15",
    "7*x0 + 2*x1 + 2*x3 >= 25",
    "7*x0 + 2*x1 + 7*x2 + 2*x3 >= 25",
    "2*x0 - x2 >= 0",
    "10*x1 - 6*x2 >= 0",
    "8*x0 + 2*x2 <= 21",
    "8*x0 + 8*x1 <= 12",
    "8*x0 + 8*x1 + 2*x2 <= 12",
    "8*x0 + 2*x2 + 6*x3 <= 43",
    "2*x1 + 2*x3 <= 90",
    "7*x0 + 2*x1 + 2*x3 <= 47"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
kale_salads = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="kale_salads")
rotisserie_chickens = m.addVar(lb=0, vtype=gp.GRB.INTEGER, name="rotisserie_chickens")
potatoes = m.addVar(lb=0, vtype=gp.GRB.INTEGER, name="potatoes")
blueberry_pies = m.addVar(lb=0, vtype=gp.GRB.INTEGER, name="blueberry_pies")

# Set objective function
m.setObjective(3*kale_salads + 7*rotisserie_chickens + 7*potatoes + 5*blueberry_pies, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(8*kale_salads + 2*potatoes >= 3)
m.addConstr(2*potatoes + 6*blueberry_pies >= 6)
m.addConstr(8*rotisserie_chickens + 6*blueberry_pies >= 8)
m.addConstr(8*kale_salads + 8*rotisserie_chickens >= 10)
m.addConstr(8*kale_salads + 8*rotisserie_chickens + 2*potatoes + 6*blueberry_pies >= 10)
m.addConstr(7*kale_salads + 7*potatoes >= 10)
m.addConstr(2*rotisserie_chickens + 2*blueberry_pies >= 18)
m.addConstr(2*rotisserie_chickens + 7*potatoes >= 9)
m.addConstr(7*kale_salads + 2*blueberry_pies >= 15)
m.addConstr(7*kale_salads + 2*rotisserie_chickens + 2*blueberry_pies >= 25)
m.addConstr(7*kale_salads + 2*rotisserie_chickens + 7*potatoes + 2*blueberry_pies >= 25)
m.addConstr(2*kale_salads - potatoes >= 0)
m.addConstr(10*rotisserie_chickens - 6*potatoes >= 0)
m.addConstr(8*kale_salads + 2*potatoes <= 21)
m.addConstr(8*kale_salads + 8*rotisserie_chickens <= 12)
m.addConstr(8*kale_salads + 8*rotisserie_chickens + 2*potatoes <= 12)
m.addConstr(8*kale_salads + 2*potatoes + 6*blueberry_pies <= 43)
m.addConstr(2*rotisserie_chickens + 2*blueberry_pies <= 90)
m.addConstr(7*kale_salads + 2*rotisserie_chickens + 2*blueberry_pies <= 47)


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))
elif m.status == gp.GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print("Optimization ended with status %d" % m.status)

```