## Problem Description and Formulation

The problem is a classic example of a linear programming problem. The sign shop produces two types of signs: storefront signs and street signs. Each type of sign requires a certain amount of time for cutting, printing, and assembly. The shop has limited hours available for each of these processes. The goal is to determine the number of each type of sign to produce in order to maximize profit.

Let's define the decision variables:

* $x_1$: number of storefront signs to produce
* $x_2$: number of street signs to produce

The objective function is to maximize profit:

* Profit per storefront sign: $400
* Profit per street sign: $120
* Total profit: $400x_1 + 120x_2

The constraints are:

* Cutting time: $2x_1 + x_2 \leq 100$
* Printing time: $x_1 + 0.5x_2 \leq 50$
* Assembly time: $2x_1 + 0.8x_2 \leq 60$
* Non-negativity: $x_1 \geq 0, x_2 \geq 0$

## Gurobi Code

```python
import gurobipy as gp

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

# Define the decision variables
x1 = m.addVar(name="storefront_signs", lb=0, ub=None, obj=400)
x2 = m.addVar(name="street_signs", lb=0, ub=None, obj=120)

# Define the constraints
m.addConstr(2*x1 + x2 <= 100, name="cutting_time")
m.addConstr(x1 + 0.5*x2 <= 50, name="printing_time")
m.addConstr(2*x1 + 0.8*x2 <= 60, name="assembly_time")

# Solve the model
m.optimize()

# Print the results
if m.status == gp.GUROBI_OPTIMAL:
    print("Optimal solution found.")
    print(f"Number of storefront signs: {x1.varValue}")
    print(f"Number of street signs: {x2.varValue}")
    print(f"Maximum profit: ${m.objVal:.2f}")
else:
    print("No optimal solution found.")
```