To solve the given optimization problem, we first need to convert the natural language description into a symbolic representation. Let's define:

- $x_1$ as the number of police officer costumes made.
- $x_2$ as the number of fireman costumes made.

The objective function is to maximize profit, which can be represented as:
\[10x_1 + 12x_2\]

Given the constraints:
1. Time constraint: It takes 10 minutes to make a police officer costume and 12 minutes to make a fireman costume, with 3000 minutes available.
\[10x_1 + 12x_2 \leq 3000\]
2. Demand constraint: The store must make at least 3 times as many fireman costumes as police officer costumes.
\[x_2 \geq 3x_1\]

Non-negativity constraints:
\[x_1 \geq 0, x_2 \geq 0\]

This gives us a symbolic representation of the problem in terms of $x_1$ and $x_2$. Now, let's put this into the requested format:

```json
{
    'sym_variables': [('x1', 'number of police officer costumes'), ('x2', 'number of fireman costumes')],
    'objective_function': '10*x1 + 12*x2',
    'constraints': ['10*x1 + 12*x2 <= 3000', 'x2 >= 3*x1', 'x1 >= 0', 'x2 >= 0']
}
```

Now, let's implement this problem using Gurobi in Python:

```python
from gurobipy import *

# Create a model
m = Model("Costume_Optimization")

# Define variables
x1 = m.addVar(name="police_officer_costumes", vtype=GRB.INTEGER, lb=0)
x2 = m.addVar(name="fireman_costumes", vtype=GRB.INTEGER, lb=0)

# Objective function: Maximize profit
m.setObjective(10*x1 + 12*x2, GRB.MAXIMIZE)

# Constraints
m.addConstr(10*x1 + 12*x2 <= 3000, name="time_constraint")
m.addConstr(x2 >= 3*x1, name="demand_constraint")

# Optimize the model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print(f"Optimal solution: {x1.varName} = {int(x1.x)} units, {x2.varName} = {int(x2.x)} units")
    print(f"Maximum profit: ${10*x1.x + 12*x2.x}")
else:
    print("No optimal solution found.")
```