Here's the formulation and the Gurobi code:

**Decision Variables:**

* `x`: Number of cat food packets purchased.
* `y`: Number of tuna cans purchased.

**Objective Function:**

Minimize the total cost:  12*x + 7*y

**Constraints:**

* Carbohydrates: 5*x + 7*y >= 700
* Vitamins: 15*x + 12*y >= 1100
* Protein: 12*x + 15*y >= 900
* Non-negativity: x, y >= 0


```python
import gurobipy as gp
from gurobipy import GRB

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

# Create decision variables
x = model.addVar(lb=0, grb=GRB.CONTINUOUS, name="cat_food_packets")
y = model.addVar(lb=0, grb=GRB.CONTINUOUS, name="tuna_cans")

# Set objective function
model.setObjective(12 * x + 7 * y, GRB.MINIMIZE)

# Add constraints
model.addConstr(5 * x + 7 * y >= 700, "carbohydrates")
model.addConstr(15 * x + 12 * y >= 1100, "vitamins")
model.addConstr(12 * x + 15 * y >= 900, "protein")

# Optimize model
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print(f"Optimal cost: ${model.objVal:.2f}")
    print(f"Number of cat food packets: {x.x:.2f}")
    print(f"Number of tuna cans: {y.x:.2f}")
elif model.status == GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print(f"Optimization ended with status {model.status}")

```
