## Problem Description and Symbolic Representation

The problem involves a glass artist who makes glass dogs and cats. The goal is to maximize profits given the time constraints for heating, molding, and cooling.

### Symbolic Representation

Let's denote:
- $x_1$ as the number of glass dogs
- $x_2$ as the number of glass cats

The objective function to maximize profit is: $50x_1 + 40x_2$

The constraints based on the available time for each process are:
- Heating: $10x_1 + 15x_2 \leq 1000$
- Molding: $30x_1 + 20x_2 \leq 1500$
- Cooling: $20x_1 + 15x_2 \leq 1200$
- Non-negativity: $x_1 \geq 0, x_2 \geq 0$

## Symbolic Representation in JSON Format

```json
{
    'sym_variables': [('x1', 'glass dogs'), ('x2', 'glass cats')],
    'objective_function': '50*x1 + 40*x2',
    'constraints': [
        '10*x1 + 15*x2 <= 1000',
        '30*x1 + 20*x2 <= 1500',
        '20*x1 + 15*x2 <= 1200',
        'x1 >= 0',
        'x2 >= 0'
    ]
}
```

## Gurobi Code in Python

```python
import gurobi

def solve_optimization_problem():
    # Create a new model
    model = gurobi.Model()

    # Define variables
    x1 = model.addVar(name="glass_dogs", lb=0, vtype=gurobi.GRB.CONTINUOUS)
    x2 = model.addVar(name="glass_cats", lb=0, vtype=gurobi.GRB.CONTINUOUS)

    # Objective function
    model.setObjective(50 * x1 + 40 * x2, gurobi.GRB.MAXIMIZE)

    # Constraints
    model.addConstr(10 * x1 + 15 * x2 <= 1000, name="heating_constraint")
    model.addConstr(30 * x1 + 20 * x2 <= 1500, name="molding_constraint")
    model.addConstr(20 * x1 + 15 * x2 <= 1200, name="cooling_constraint")

    # Optimize
    model.optimize()

    # Print solution
    if model.status == gurobi.GRB.OPTIMAL:
        print(f"Optimal solution: glass dogs = {x1.varValue}, glass cats = {x2.varValue}")
        print(f"Max profit: ${model.objVal:.2f}")
    else:
        print("No optimal solution found")

solve_optimization_problem()
```