To solve the given optimization problem, we need to define the variables and constraints in a way that Gurobi can understand. The variables are 'bowls of cereal', 'bowls of instant ramen', and 'tomatoes'. We want to minimize the objective function: 3 * (amount of bowls of cereal) + 3 * (quantity of bowls of instant ramen) + 7 * (number of tomatoes).

The constraints given can be grouped into three categories:
1. Constraints related to umami index.
2. Constraints related to grams of protein.
3. Additional linear constraints.

We will model each constraint using Gurobi's Python API, ensuring that we capture all the details provided in the problem description.

Here is how we translate the natural language description into functional Gurobi code:

```python
from gurobipy import *

# Create a new model
m = Model("Optimization_Problem")

# Define variables
bowls_of_cereal = m.addVar(lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="bowls_of_cereal")
bowls_of_instant_ramen = m.addVar(lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="bowls_of_instant_ramen")
tomatoes = m.addVar(lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS, name="tomatoes")

# Define the objective function
m.setObjective(3 * bowls_of_cereal + 3 * bowls_of_instant_ramen + 7 * tomatoes, GRB.MINIMIZE)

# Constraints related to umami index
m.addConstr(11 * bowls_of_cereal + 13 * bowls_of_instant_ramen >= 108, name="umami_index_min_1")
m.addConstr(11 * bowls_of_cereal + 24 * tomatoes >= 90, name="umami_index_min_2")
m.addConstr(11 * bowls_of_cereal + 13 * bowls_of_instant_ramen + 24 * tomatoes >= 90, name="umami_index_min_3")
m.addConstr(11 * bowls_of_cereal + 13 * bowls_of_instant_ramen <= 319, name="umami_index_max_1")
m.addConstr(11 * bowls_of_cereal + 24 * tomatoes <= 303, name="umami_index_max_2")

# Constraints related to grams of protein
m.addConstr(18 * bowls_of_cereal + 5 * bowls_of_instant_ramen >= 42, name="protein_min_1")
m.addConstr(18 * bowls_of_cereal + 8 * tomatoes >= 67, name="protein_min_2")
m.addConstr(5 * bowls_of_instant_ramen + 8 * tomatoes >= 106, name="protein_min_3")
m.addConstr(18 * bowls_of_cereal + 5 * bowls_of_instant_ramen + 8 * tomatoes >= 63, name="protein_min_4")

# Additional linear constraints
m.addConstr(-2 * bowls_of_cereal + 6 * tomatoes >= 0, name="additional_constraint_1")
m.addConstr(9 * bowls_of_cereal - 2 * bowls_of_instant_ramen >= 0, name="additional_constraint_2")

# Optimize model
m.optimize()

# Print solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found.")
    print(f"bowls_of_cereal: {bowls_of_cereal.x}")
    print(f"bowls_of_instant_ramen: {bowls_of_instant_ramen.x}")
    print(f"tomatoes: {tomatoes.x}")
else:
    print("No optimal solution found.")

```