```json
{
  "sym_variables": [
    ("x0", "milligrams of potassium"),
    ("x1", "milligrams of vitamin D"),
    ("x2", "milligrams of vitamin B1")
  ],
  "objective_function": "5.1 * x0 + 6.54 * x1 + 7.3 * x2",
  "constraints": [
    "16 * x0 + 5 * x1 >= 20",
    "16 * x0 + 5 * x1 + 8 * x2 >= 20",
    "2 * x1 - 3 * x2 >= 0",
    "7 * x0 - 5 * x1 >= 0"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
potassium = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="potassium")
vitamin_d = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="vitamin_d")
vitamin_b1 = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="vitamin_b1")


# Set objective function
m.setObjective(5.1 * potassium + 6.54 * vitamin_d + 7.3 * vitamin_b1, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(16 * potassium + 5 * vitamin_d >= 20, "digestive_support_1")
m.addConstr(16 * potassium + 5 * vitamin_d + 8 * vitamin_b1 >= 20, "digestive_support_2")
m.addConstr(2 * vitamin_d - 3 * vitamin_b1 >= 0, "vitamin_ratio")
m.addConstr(7 * potassium - 5 * vitamin_d >= 0, "potassium_vitamin_d_ratio")


# Optimize model
m.optimize()

if m.status == gp.GRB.OPTIMAL:
    print('Optimal objective: %g' % m.objVal)
    print('Potassium: %g' % potassium.x)
    print('Vitamin D: %g' % vitamin_d.x)
    print('Vitamin B1: %g' % vitamin_b1.x)
elif m.status == gp.GRB.INF_OR_UNBD:
    print('Model is infeasible or unbounded')
    exit(0)
elif m.status == gp.GRB.INFEASIBLE:
    print('Model is infeasible')
    exit(0)
elif m.status == gp.GRB.UNBOUNDED:
    print('Model is unbounded')
    exit(0)
else:
    print('Optimization ended with status %d' % m.status)
    exit(0)

```