Here's the formulation of the linear program and the Gurobi code to solve it:

**Decision Variables:**

* `x`: Number of low-quality face washes produced.
* `y`: Number of medium-quality face washes produced.
* `z`: Number of high-quality face washes produced.

**Objective Function:**

Maximize profit: `3x + 7y + 9z`

**Constraints:**

* **Rare Ingredients:** `1x + 3y + 4z <= 100`
* **Water:** `4x + 2y + 1z <= 200`
* **Non-negativity:** `x, y, z >= 0`


```python
import gurobipy as gp

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

# Create variables
x = m.addVar(vtype=gp.GRB.CONTINUOUS, name="low_quality")
y = m.addVar(vtype=gp.GRB.CONTINUOUS, name="medium_quality")
z = m.addVar(vtype=gp.GRB.CONTINUOUS, name="high_quality")

# Set objective function
m.setObjective(3*x + 7*y + 9*z, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(1*x + 3*y + 4*z <= 100, "rare_ingredients")
m.addConstr(4*x + 2*y + 1*z <= 200, "water")

# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print(f"Optimal profit: {m.objVal}")
    print(f"Low quality face washes: {x.x}")
    print(f"Medium quality face washes: {y.x}")
    print(f"High quality face washes: {z.x}")
else:
    print("Infeasible or unbounded")

```
