```json
{
  "sym_variables": [
    ("x1", "printed art"),
    ("x2", "painting")
  ],
  "objective_function": "5*x1 + 8*x2",
  "constraints": [
    "10*x1 + 0*x2 <= 150",
    "5*x1 + 15*x2 <= 400",
    "x1 >= 0",
    "x2 >= 0"
  ]
}
```

```python
import gurobipy as gp

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

# Create variables
printed_art = m.addVar(vtype=gp.GRB.CONTINUOUS, name="printed_art")  # Number of printed arts
painting = m.addVar(vtype=gp.GRB.CONTINUOUS, name="painting")  # Number of paintings


# Set objective function
m.setObjective(5 * printed_art + 8 * painting, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(10 * printed_art + 0 * painting <= 150, "Printing_Time")
m.addConstr(5 * printed_art + 15 * painting <= 400, "Framing_Time")
m.addConstr(printed_art >= 0, "Non_Negative_Printed_Art")  # Ensure non-negative values
m.addConstr(painting >= 0, "Non_Negative_Painting")  # Ensure non-negative values


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print(f"Optimal profit: ${m.objVal:.2f}")
    print(f"Number of printed arts: {printed_art.x:.2f}")
    print(f"Number of paintings: {painting.x:.2f}")
elif m.status == gp.GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print(f"Optimization ended with status {m.status}")

```
