```json
{
  "sym_variables": [
    ("x0", "bowls of pasta"),
    ("x1", "oranges"),
    ("x2", "tomatoes"),
    ("x3", "ravioli")
  ],
  "objective_function": "7*x0 + 3*x1 + 7*x2 + 5*x3",
  "constraints": [
    "18*x0 + 6*x2 >= 14",
    "18*x0 + 18*x1 >= 15",
    "18*x0 + 6*x2 + 16*x3 >= 24",
    "18*x1 + 6*x2 + 16*x3 >= 24",
    "18*x0 + 6*x2 + 16*x3 >= 38",
    "18*x1 + 6*x2 + 16*x3 >= 38",
    "18*x0 + 18*x1 + 6*x2 + 16*x3 >= 38",
    "4*x0 + 19*x3 >= 31",
    "6*x2 + 19*x3 >= 27",
    "4*x0 + 9*x1 >= 31",
    "9*x1 + 6*x2 >= 25",
    "4*x0 + 9*x1 + 6*x2 >= 32",
    "4*x0 + 6*x2 + 19*x3 >= 32",
    "4*x0 + 9*x1 + 6*x2 >= 26",
    "4*x0 + 6*x2 + 19*x3 >= 26",
    "4*x0 + 9*x1 + 6*x2 + 19*x3 >= 26",
    "6*x1 - 4*x2 >= 0",
    "18*x1 + 16*x3 <= 149",
    "18*x0 + 18*x1 <= 124",
    "18*x1 + 6*x2 <= 139",
    "6*x2 + 16*x3 <= 72",
    "18*x0 + 18*x1 + 6*x2 <= 159",
    "6*x2 + 19*x3 <= 56",
    "4*x0 + 19*x3 <= 42",
    "9*x1 + 19*x3 <= 108",
    "4*x0 + 9*x1 <= 122",
    "4*x0 + 6*x2 + 19*x3 <= 113"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
pasta = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="bowls_of_pasta")
oranges = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="oranges")
tomatoes = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="tomatoes")
ravioli = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="ravioli")

# Set objective function
m.setObjective(7*pasta + 3*oranges + 7*tomatoes + 5*ravioli, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(18*pasta + 6*tomatoes >= 14)
m.addConstr(18*pasta + 18*oranges >= 15)
m.addConstr(18*pasta + 6*tomatoes + 16*ravioli >= 24)
m.addConstr(18*oranges + 6*tomatoes + 16*ravioli >= 24)
m.addConstr(18*pasta + 6*tomatoes + 16*ravioli >= 38)
m.addConstr(18*oranges + 6*tomatoes + 16*ravioli >= 38)
m.addConstr(18*pasta + 18*oranges + 6*tomatoes + 16*ravioli >= 38)
m.addConstr(4*pasta + 19*ravioli >= 31)
m.addConstr(6*tomatoes + 19*ravioli >= 27)
m.addConstr(4*pasta + 9*oranges >= 31)
m.addConstr(9*oranges + 6*tomatoes >= 25)
m.addConstr(4*pasta + 9*oranges + 6*tomatoes >= 32)
m.addConstr(4*pasta + 6*tomatoes + 19*ravioli >= 32)
m.addConstr(4*pasta + 9*oranges + 6*tomatoes >= 26)
m.addConstr(4*pasta + 6*tomatoes + 19*ravioli >= 26)
m.addConstr(4*pasta + 9*oranges + 6*tomatoes + 19*ravioli >= 26)
m.addConstr(6*oranges - 4*tomatoes >= 0)
m.addConstr(18*oranges + 16*ravioli <= 149)
m.addConstr(18*pasta + 18*oranges <= 124)
m.addConstr(18*oranges + 6*tomatoes <= 139)
m.addConstr(6*tomatoes + 16*ravioli <= 72)
m.addConstr(18*pasta + 18*oranges + 6*tomatoes <= 159)
m.addConstr(6*tomatoes + 19*ravioli <= 56)
m.addConstr(4*pasta + 19*ravioli <= 42)
m.addConstr(9*oranges + 19*ravioli <= 108)
m.addConstr(4*pasta + 9*oranges <= 122)
m.addConstr(4*pasta + 6*tomatoes + 19*ravioli <= 113)


# 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 problem is infeasible.')
else:
    print('Optimization ended with status %d' % m.status)

```