## Symbolic Representation

Let's denote:
- $x_1$ as the units of essential oil
- $x_2$ as the units of fruit scent

The problem can be symbolically represented as:

```json
{
    'sym_variables': [('x1', 'essential oil'), ('x2', 'fruit scent')],
    'objective_function': '3.5*x1 + 2*x2',
    'constraints': [
        '3*x1 + 10*x2 >= 6',  # At least 6 units of aromatic notes
        '9*x1 + 4*x2 >= 7',   # Lasts at least for 7 hours
        '3*x1 + 10*x2 <= 8',  # At most 8 units of aromatic notes
        'x1 >= 0', 'x2 >= 0'  # Non-negativity constraints
    ]
}
```

## Gurobi Code

```python
import gurobi

def solve_fragrance_mixture_problem():
    # Create a new model
    model = gurobi.Model()

    # Define variables
    x1 = model.addVar(name="essential_oil", lb=0)  # Units of essential oil
    x2 = model.addVar(name="fruit_scent", lb=0)   # Units of fruit scent

    # Objective function: Minimize cost
    model.setObjective(3.5 * x1 + 2 * x2, gurobi.GRB.MINIMIZE)

    # Constraints
    model.addConstr(3 * x1 + 10 * x2 >= 6, name="aromatic_notes")  # At least 6 units of aromatic notes
    model.addConstr(9 * x1 + 4 * x2 >= 7, name="duration")        # Lasts at least for 7 hours
    model.addConstr(3 * x1 + 10 * x2 <= 8, name="max_aromatic_notes")  # At most 8 units of aromatic notes

    # Optimize
    model.optimize()

    # Print solution
    if model.status == gurobi.GRB.OPTIMAL:
        print(f"Optimal solution: x1 = {x1.varValue}, x2 = {x2.varValue}")
        print(f"Minimum cost: {model.objVal}")
    else:
        print("No optimal solution found.")

solve_fragrance_mixture_problem()
```