Here's the formulation and Gurobi code for the optimization problem:

**Decision Variables:**

* `x1`: Number of commercials with famous actors
* `x2`: Number of commercials with regular people
* `x3`: Number of commercials with no people

**Objective Function:**

Maximize total viewership: `50000*x1 + 20000*x2 + 18000*x3`

**Constraints:**

* **Budget Constraint:** `10000*x1 + 3000*x2 + 2000*x3 <= 50000`
* **Regular People Commercial Limit:** `x2 <= 3`
* **No People Commercial Proportion:** `x3 <= (x1 + x2 + x3) / 3`
* **Famous Actor Commercial Proportion:** `x1 >= 0.2 * (x1 + x2 + x3)`
* **Non-negativity:** `x1, x2, x3 >= 0`
* **Integer Constraint:** `x1, x2, x3` must be integers


```python
import gurobipy as gp

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

# Create variables
x1 = model.addVar(vtype=gp.GRB.INTEGER, name="famous_actor_commercials")
x2 = model.addVar(vtype=gp.GRB.INTEGER, name="regular_people_commercials")
x3 = model.addVar(vtype=gp.GRB.INTEGER, name="no_people_commercials")

# Set objective function
model.setObjective(50000*x1 + 20000*x2 + 18000*x3, gp.GRB.MAXIMIZE)

# Add constraints
model.addConstr(10000*x1 + 3000*x2 + 2000*x3 <= 50000, "budget_constraint")
model.addConstr(x2 <= 3, "regular_people_limit")
model.addConstr(x3 <= (x1 + x2 + x3) / 3, "no_people_proportion")
model.addConstr(x1 >= 0.2 * (x1 + x2 + x3), "famous_actor_proportion")


# Optimize model
model.optimize()

# Print results
if model.status == gp.GRB.OPTIMAL:
    print(f"Optimal Viewership: {model.objVal}")
    print(f"Number of famous actor commercials: {x1.x}")
    print(f"Number of regular people commercials: {x2.x}")
    print(f"Number of no people commercials: {x3.x}")
elif model.status == gp.GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    print(f"Optimization ended with status {model.status}")

```
