Title: linear programming python gurobi
Tags: python,mathematical-optimization,linear-programming,gurobi

Question: I am working on a single machine scheduling problem where the goal is to minimize weighted delay. I have created a model using Python/Gurobi, but I'm experiencing issues with the objective function as it is producing suboptimal results. Interestingly, when I transfer the model to OpenSolver in Excel, I get better results.
import gurobipy as gp


N = 15 # number of jobs

# w: weights of jobs
w = [1, 10, 9, 10, 10, 4, 3, 2, 10, 3, 7, 3, 1, 3, 10]

# p: process time of jobs
p = [26, 24, 79, 46, 32, 35, 73, 74, 14, 67, 86, 46, 78, 40, 29]

# d: due dates of jobs
d = [397, 405, 433, 443, 424, 372, 392, 461, 432, 409, 400, 385, 464, 411, 427]

# Create a new model
m = gp.Model()
x = {}
goal = m.addVar(vtype=gp.GRB.CONTINUOUS)

#T : Tardiness

#C : Completion time

T = m.addVars(N,lb=0)
C = m.addVars(N)
K = m.addVars(N)
weight = {j: w[j] for j in range(N)}

#x[i,j]:The variable xij is a variable that takes a value of 1 when Job i is assigned to Sequence j, and takes a value of 0 in all other cases.

for i in range(N):
    for j in range(N):
        x[i,j] = m.addVar(vtype=gp.GRB.BINARY)
        
# Set objective function: "The sequencing of jobs in a way that minimizes the total weighted delay."

m.setObjective((goal), gp.GRB.MINIMIZE)

# Add constraints

# Constraint1: Each job must be assigned to a sequence.

for i in range(N):
    m.addConstr(gp.quicksum(x[i,j] for j in range(N)) == 1)

#Constraint2: Each sequence must be assigned a job.

for j in range(N):
    m.addConstr(gp.quicksum(x[i,j] for i in range(N)) == 1)
    
    
#Constraint3: If Job i is assigned to Sequence j, then the processing time of Job i is assigned to Sequence j.

for j in range(N):
    m.addConstr(gp.quicksum(p[i]*x[i,j] for i in range(N)) == K[j])
    
#Constraint4: If Job i is assigned to Sequence j, then the weight of Job i is assigned to Sequence j.

for j in range(N):
   m.addConstr(gp.quicksum(w[i]*x[i,j] for i in range(N)) == weight[j])
   

#Constraint 5: The completion time of Sequence j is the sum of the completion time of the previous sequence and the processing time of the job assigned to Sequence j.
  
C[0].lb = 0
for j in range(1, N):
    m.addConstr(C[j-1] + K[j] == C[j])

#Constraint 6: If the completion time is greater than the due date, then there is a tardiness.
for j in range(N):
    m.addConstr(T[j] >= C[j] - gp.quicksum(x[i,j]*d[i] for i in range(N)))

#goal: The sequencing of jobs in a way that minimizes the total weighted tardiness.
m.addConstr(gp.quicksum(T[j]*weight[j] for j in range (N)) <= goal)

m.addConstr(C[0] == K[0])
m.addConstr(T[0] >= C[0] - d[0])
# Solve the problem
m.optimize()

# Print solution
print('Optimal objective value: %g' % m.objVal)
print('Solution:')
for i in range(N):
    for j in range(N):
        if x[i,j].X > 0.5:
            print('x[%d,%d] = %d' % (i,j,x[i,j].X))

I would appreciate any assistance in improving the objective function in my Python/Gurobi model to match the results obtained from OpenSolver in Excel.

Answer: You should write out the LP file for both approaches to see whether they differ at some point. This is generally recommended to double-check your formulation and see whether it actually matches the mathematical model.