```json
{
  "sym_variables": [
    ("x0", "blue highlighters"),
    ("x1", "3D printers"),
    ("x2", "lanyards"),
    ("x3", "hole punches")
  ],
  "objective_function": "1.75 * x0 + 9.74 * x1 + 8.21 * x2 + 2.83 * x3",
  "constraints": [
    "26 * x0 + 32 * x1 + 24 * x2 + 7 * x3 <= 445",  // storage space
    "1 * x0 + 18 * x1 + 22 * x2 + 22 * x3 <= 445",  // sustainability score
    "26 * x0 + 7 * x3 >= 97",
    "32 * x1 + 7 * x3 >= 94",
    "24 * x2 + 7 * x3 >= 45",
    "26 * x0 + 24 * x2 >= 49",
    "1 * x0 + 22 * x3 >= 64",
    "1 * x0 + 22 * x2 >= 37",
    "1 * x0 + 18 * x1 + 22 * x2 >= 87",
    "18 * x1 + 22 * x2 + 22 * x3 >= 87",
    "1 * x0 + 18 * x1 + 22 * x2 >= 55",
    "18 * x1 + 22 * x2 + 22 * x3 >= 55",
    "-9 * x0 + 10 * x1 >= 0",
    "26 * x0 + 32 * x1 <= 336",
    "24 * x2 + 7 * x3 <= 433",
    "26 * x0 + 24 * x2 + 7 * x3 <= 398",
    "26 * x0 + 32 * x1 + 7 * x3 <= 350",
    "32 * x1 + 24 * x2 + 7 * x3 <= 279",
    "26 * x0 + 32 * x1 + 24 * x2 + 7 * x3 <= 279",
    "22 * x2 + 22 * x3 <= 291",
    "1 * x0 + 22 * x3 <= 414",
    "1 * x0 + 18 * x1 <= 291",
    "1 * x0 + 22 * x2 <= 277",
    "1 * x0 + 18 * x1 + 22 * x2 <= 147",
    "18 * x1 + 22 * x2 + 22 * x3 <= 282",
    "1 * x0 + 18 * x1 + 22 * x2 + 22 * x3 <= 282",
    "x0, x1, x2, x3 are integers"
  ]
}
```

```python
import gurobipy as gp

try:
    # Create a new model
    m = gp.Model("optimization_problem")

    # Create variables
    x = m.addVars(4, vtype=gp.GRB.INTEGER, name=["blue highlighters", "3D printers", "lanyards", "hole punches"])

    # Set objective function
    m.setObjective(1.75 * x[0] + 9.74 * x[1] + 8.21 * x[2] + 2.83 * x[3], gp.GRB.MAXIMIZE)

    # Add constraints
    m.addConstr(26 * x[0] + 32 * x[1] + 24 * x[2] + 7 * x[3] <= 445, "storage_space")
    m.addConstr(1 * x[0] + 18 * x[1] + 22 * x[2] + 22 * x[3] <= 445, "sustainability_score")
    m.addConstr(26 * x[0] + 7 * x[3] >= 97)
    m.addConstr(32 * x[1] + 7 * x[3] >= 94)
    m.addConstr(24 * x[2] + 7 * x[3] >= 45)
    m.addConstr(26 * x[0] + 24 * x[2] >= 49)
    m.addConstr(1 * x[0] + 22 * x[3] >= 64)
    m.addConstr(1 * x[0] + 22 * x[2] >= 37)
    m.addConstr(1 * x[0] + 18 * x[1] + 22 * x[2] >= 87)
    m.addConstr(18 * x[1] + 22 * x[2] + 22 * x[3] >= 87)
    m.addConstr(1 * x[0] + 18 * x[1] + 22 * x[2] >= 55)
    m.addConstr(18 * x[1] + 22 * x[2] + 22 * x[3] >= 55)
    m.addConstr(-9 * x[0] + 10 * x[1] >= 0)
    m.addConstr(26 * x[0] + 32 * x[1] <= 336)
    m.addConstr(24 * x[2] + 7 * x[3] <= 433)
    m.addConstr(26 * x[0] + 24 * x[2] + 7 * x[3] <= 398)
    m.addConstr(26 * x[0] + 32 * x[1] + 7 * x[3] <= 350)
    m.addConstr(32 * x[1] + 24 * x[2] + 7 * x[3] <= 279)
    m.addConstr(26 * x[0] + 32 * x[1] + 24 * x[2] + 7 * x[3] <= 279)
    m.addConstr(22 * x[2] + 22 * x[3] <= 291)
    m.addConstr(1 * x[0] + 22 * x[3] <= 414)
    m.addConstr(1 * x[0] + 18 * x[1] <= 291)
    m.addConstr(1 * x[0] + 22 * x[2] <= 277)
    m.addConstr(1 * x[0] + 18 * x[1] + 22 * x[2] <= 147)
    m.addConstr(18 * x[1] + 22 * x[2] + 22 * x[3] <= 282)
    m.addConstr(1 * x[0] + 18 * x[1] + 22 * x[2] + 22 * x[3] <= 282)


    # Optimize model
    m.optimize()

    if m.status == gp.GRB.OPTIMAL:
        for v in m.getVars():
            print('%s %g' % (v.varName, v.x))
        print('Obj: %g' % m.objVal)
    elif m.status == gp.GRB.INFEASIBLE:
        print('The model is infeasible.')
    else:
        print('Optimization ended with status %d' % m.status)


except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))

except AttributeError:
    print('Encountered an attribute error')
```