Thank you, guys. I have slightly modified the code to fill in data automatically from the .csv files in the google drive. It seems the code works well.
from google.colab import drive
drive.mount('/content/drive')
!pip install pulp
import numpy as np
import pandas as pd
import pulp
#import data
path="/content/drive/MyDrive/Colab Notebooks/LPanelProduction/"
jobmold=pd.read_csv(path+"jobmold.csv")
jobmoldcontent=jobmold.iloc[:,0].tolist()
jn=len(jobmoldcontent)
jobmoldcontentdata=[]
for i in range(jn):
jobmoldcontentdata.append(jobmoldcontent[i].split('|'))
molddata=[]
for i in range(jn):
temp=jobmoldcontentdata[i][3]
molddata.append(int(temp))
def count_distinct_np(arr):
return len(np.unique(arr))
mn=count_distinct_np(molddata)
moldchangecost=pd.read_csv(path+"moldchangecost.csv")
moldchangecostcontent=moldchangecost.iloc[:,0].tolist()
moldchangecostcontentdata=[]
for i in range(len(moldchangecostcontent)):
moldchangecostcontentdata.append(moldchangecostcontent[i].split('|'))
moldchangecostdata=[]
for i in range(mn):
for j in range(mn):
moldchangecostdata_row=[]
for k in range(len(moldchangecostcontentdata)):
temp1=moldchangecostcontentdata[k][1] #prev_mold_ID
temp2=moldchangecostcontentdata[k][3] #next_mold_ID
temp3=moldchangecostcontentdata[k][4] #cost
if int(temp1)==i+1 and int(temp2)==j+1: moldchangecostdata.append(int(temp3))
#main
molds=pd.Series(index=pd.RangeIndex(name='job',start=1,stop=jn+1),
name='mold',data=molddata)
prev_mold_idx = pd.RangeIndex(name='prev_mold', start=1, stop=mn+1)
next_mold_idx = pd.RangeIndex(name='next_mold', start=1, stop=mn+1)
mold_change_costs = pd.Series(
index=pd.MultiIndex.from_product((prev_mold_idx, next_mold_idx)),
name='cost', data=moldchangecostdata,
)
job_change_idx = pd.MultiIndex.from_product(
(molds.index, molds.index),
names=('source_job', 'dest_job'),
)
job_changes = pd.Series(
index=job_change_idx,
name='job_change',
data=pulp.LpVariable.matrix(
name='job_change', indices=job_change_idx, cat=pulp.LpBinary,
),
)
mold_change_idx = pd.MultiIndex.from_product((
pd.RangeIndex(name='prev_job', start=1, stop=len(molds)),
prev_mold_idx, next_mold_idx,
))
mold_change_idx = mold_change_idx[
mold_change_idx.get_level_values('prev_mold') != mold_change_idx.get_level_values('next_mold')
]
all_mold_costs = pd.Series(
index=mold_change_idx,
name='mold_cost',
data=pulp.LpVariable.matrix(
name='mold_cost', indices=mold_change_idx, cat=pulp.LpContinuous, lowBound=0,
),
)
prob = pulp.LpProblem(name='job_sequence', sense=pulp.LpMinimize)
prob.setObjective(pulp.lpSum(all_mold_costs))
# Job changes must be assigned exclusively
for source_job, subtotal in job_changes.groupby('source_job').sum().items():
prob.addConstraint(
name=f'excl_s{source_job}',
constraint=1 == subtotal,
)
for dest_job, subtotal in job_changes.groupby('dest_job').sum().items():
prob.addConstraint(
name=f'excl_d{dest_job}',
constraint=1 == subtotal,
)
for (prev_job, prev_mold, next_mold), cost in all_mold_costs.items():
# if both the relevant prev job and next job are assigned, this is the cost
cost_if_assigned = mold_change_costs[(prev_mold, next_mold)]
# series of job assignment variables for any source job having 'prev_mold', and dest job 'prev_job'
prev_job_changes = job_changes.loc[(molds.index[molds == prev_mold], prev_job)]
# series of job assignment variables for any source job having 'next_mold', and dest job 'next_job'
next_job = prev_job + 1
next_job_changes = job_changes.loc[(molds.index[molds == next_mold], next_job)]
prob.addConstraint(
name=f'cost_j{prev_job}_j{next_job}_m{prev_mold}_m{next_mold}',
constraint=cost >= cost_if_assigned*(
-1 + pulp.lpSum(prev_job_changes) + pulp.lpSum(next_job_changes)
),
)
print(prob)
prob.solve()
assert prob.status == pulp.LpStatusOptimal
print('Job changes:')
job_changes = job_changes.apply(pulp.value).unstack(level='dest_job').astype(np.int8)
print(job_changes)
print()
job_changes.to_csv(path+"jobsequenceresult.csv")
print('All mold costs:')
all_mold_costs = all_mold_costs.apply(pulp.value).unstack(
level=['prev_mold', 'next_mold'],
).astype(np.int8)
print(all_mold_costs)
print()
print('Job sequence:')
i, j = job_changes.values.T.nonzero()
print(molds.iloc[j])