## Symbolic Representation

To solve the problem described, we first need to convert the natural language description into a symbolic representation. Let's define the variables and the objective function, as well as the constraints.

### Variables
- $x_1$ = Number of trucks
- $x_2$ = Number of vans

### Objective Function
The objective is to maximize the total number of potatoes transported. Each truck can take 150 potatoes, and each van can take 80 potatoes. Therefore, the objective function can be represented as:
\[ \text{Maximize:} \quad 150x_1 + 80x_2 \]

### Constraints
1. The cost of running each truck is $20, and the cost of running each van is $12. Bob wants to spend at most $250 on transporting his potatoes.
\[ 20x_1 + 12x_2 \leq 250 \]
2. Due to traffic laws, the number of trucks must be less than the number of vans.
\[ x_1 < x_2 \]
3. The number of trucks and vans cannot be negative.
\[ x_1 \geq 0, \quad x_2 \geq 0 \]
4. Since $x_1$ and $x_2$ represent the number of trucks and vans, they must be integers.
\[ x_1 \in \mathbb{Z}, \quad x_2 \in \mathbb{Z} \]

However, for a linear programming (LP) problem, we typically relax the integrality constraints and solve the LP relaxation. If the solution to the LP relaxation is integral, it is also a solution to the integer program.

## Symbolic Representation in JSON Format

```json
{
    'sym_variables': [('x1', 'trucks'), ('x2', 'vans')],
    'objective_function': '150*x1 + 80*x2',
    'constraints': [
        '20*x1 + 12*x2 <= 250',
        'x1 < x2',
        'x1 >= 0',
        'x2 >= 0'
    ]
}
```

## Gurobi Code in Python

```python
import gurobi

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

    # Define variables
    x1 = model.addVar(name='trucks', lb=0, vtype=gurobi.GRB.INTEGER)  # Number of trucks
    x2 = model.addVar(name='vans', lb=0, vtype=gurobi.GRB.INTEGER)   # Number of vans

    # Objective function: Maximize 150*x1 + 80*x2
    model.setObjective(150*x1 + 80*x2, gurobi.GRB.MAXIMIZE)

    # Constraints
    model.addConstr(20*x1 + 12*x2 <= 250, name='cost_constraint')  # Cost constraint
    model.addConstr(x1 <= x2 - 1, name='truck_van_constraint')     # Truck-Van constraint, converted to <= for MIP

    # Solve the model
    model.optimize()

    # Print solution
    if model.status == gurobi.GRB.OPTIMAL:
        print(f"Optimal number of trucks: {x1.varValue}")
        print(f"Optimal number of vans: {x2.varValue}")
        print(f"Maximum potatoes transported: {150*x1.varValue + 80*x2.varValue}")
    else:
        print("The problem is infeasible.")

solve_potato_transportation()
```