import random from types import * from sets import * class fridata: """class for holding/producing the data required to in FRI/JT problem required fields: MIP DATA * T - number of periods (in the MIP/big bucket model) * Period - the list 1..T, i.e.range(1,T+1) * Prod - list of products * Blck - list of blocks * Compat[p] - (dict) -> list of compatible blocks for each product 'p' * SetUpTime[p,b,t] - setup time for 'p','b','t' (to be input from scheduling) * SetUpCost - (default value) for the setup cost !!! * VariableCost - (default value) for the variable cost !!! * HoldingCost - (default value) for the holding cost !!! * BacklogCost - (default value) for the backlog cost !!! * MaxRate[p,m,t] - maximum rate of production of 'p' on block 'm', period 't' * WorkHours[m,t] - available working hours on block 'm', period 't' * Demand[p,t] - demand for 'p' on 't' (can be instantiated with mkdemand) SCHEDULING DATA * H - number of subperiods (i.e., hours in a month) * Unaval[m,h] - mark unavailable subperiods in a period (can be extracted from WorkHours) * Compat - (as for MIP) * Mach[b] - list of machines in block 'b' * iRate[p,m,t] - capacity of individual machine 'm' (not block) * iSetUpTime[p,m,t] - setup time for individual machine 'm' (not block) * iChangeOverTime[p,m,t] - change over time for individual machine 'm' (not block) * iSetUpCost[p,m,t] - setup cost for individual machine 'm' (not block) * iChangeOverCost[p,m,t] - change over cost for individual machine 'm' (not block) """ def mk_const_demand(self, Dem): "make constant monthly demand equal to the average monthly demand for each prod" "Dem[prod] is the monthly demand for prod" self.Demand = {} for p in self.Prod: for t in self.Period: self.Demand[p,t] = Dem[p] def mk_rnd_demand(self, Dem): "make random yearly demand based on average monthly demand for each prod" "Dem[prod] is the monthly demand for prod" self.Demand = {} for p in self.Prod: for t in self.Period: self.Demand[p,t] = random.randint(0,int(2.*Dem[p])) def printparam(self, f, name, var): if type(var) is DictType: print >>f, "param %s := " % name keys = var.keys() keys.sort() for key in keys: print >>f, " ".join([str(i) for i in key]), var[key] print >>f, ";" else: print >>f, "param %s default %f;" % (name, var) def mkampl(self, filename, CUT = {}): "write file with all the variables in AMPL data syntax" f = open(filename, "w") print >>f, "param T := ", self.T, ';' print >>f, "set Prod := " + " ".join(self.Prod) + ';' print >>f, "set Blck := " + " ".join(self.Blck) + ';' for p in self.Prod: print >>f, "set Compat[%s] := " % p, print >>f, " ".join([str(i) for i in self.Compat[p]]), print >>f, ";" self.printparam(f, "SetUpCost", self.SetUpCost) self.printparam(f, "VariableCost", self.VariableCost) self.printparam(f, "HoldingCost", self.HoldingCost) self.printparam(f, "BacklogCost", self.BacklogCost) self.printparam(f, "SetUpTime", self.SetUpTime) self.printparam(f, "MaxRate", self.MaxRate) self.printparam(f, "WorkHours", self.WorkHours) self.printparam(f, "Demand", self.Demand) if CUT != {}: self.printparam(f, "CUT", CUT) print >>f, "end;" toy = fridata() toy.T = 3 toy.Period = range(1,toy.T+1) toy.Prod = [ 'p1', 'p2', 'p3', ] toy.Blck = [ 'b1', 'b2', 'b3', ] toy.Compat = { 'p1': toy.Blck[:], 'p2': toy.Blck[1:2], 'p3': toy.Blck[2:], } toy.BlckMach = { 'b1': ['m1', 'm2', 'm3', 'm4'], 'b2': ['m5', 'm6'], 'b3': ['m7', 'm8'], } toy.Mach = [] for i in toy.BlckMach.values(): for m in i: toy.Mach.append(m) toy.SetUpCost = .070000 toy.VariableCost = 1.188298 toy.HoldingCost = 0.100000 toy.BacklogCost = 1000000 toy.TotalWorkHours = { 1: 21 * 8, 2: 19 * 8, 3: 21 * 8, } toy.Unavailable = { ('b1',1): 0 * 1 * 8, ('b1',2): 0 * 19 * 8, ('b1',3): 0 * 3 * 8, ('b2',1): 0 * 4 * 8, ('b2',3): 0 * 4 * 8, } toy.WorkHours = {} for b in toy.Blck: for t in toy.Period: toy.WorkHours[b,t] = toy.TotalWorkHours[t] if (b,t) in toy.Unavailable.keys(): toy.WorkHours[b,t] -= toy.Unavailable[b,t] assert toy.WorkHours[b,t] >= 0 toy.iRate = {} # production rate (M units/h) (values extracted considering 8 working hours/day) for p in toy.Prod: toy.iRate[p,'m1'] = 1.05 * 9.7/8. # !!! not necessary for all p, but ... toy.iRate[p,'m2'] = 1.05 * 15./8. toy.iRate[p,'m3'] = 1.05 * 9.6/8. toy.iRate[p,'m4'] = 1.05 * 15./8. toy.iRate[p,'m5'] = 1.05 * 9.8/8. toy.iRate[p,'m6'] = 1.05 * 15./8. toy.iRate[p,'m7'] = 1.05 * 9.2/8. toy.iRate[p,'m8'] = 1.05 * 15./8. toy.MaxRate = {} for p in toy.Prod: for b in toy.Compat[p]: toy.MaxRate[p,b] = sum([toy.iRate[p,m] for m in toy.BlckMach[b]]) setuptime = 3.5 toy.SetUpTime = {} for p in toy.Prod: for b in toy.Compat[p]: for t in toy.Period: toy.SetUpTime[p,b,t] = setuptime Dem = { 'p1': 1023, 'p2': 518, 'p3': 513, } toy.mk_const_demand(Dem) # toy.mk_rnd_demand(Dem) ###################################################################### ###################################################################### ###################################################################### jt = fridata() jt.T = 12 jt.Period = range(1,jt.T+1) jt.Prod = [ 'p11380000', 'p12000000', 'p12230000', 'p12640000', 'p13120000', 'p13550000', 'p13680000', 'p13690000', 'p60608051', 'p60615162', 'p60717R51', 'p60718052', ] jt.Blck = [ 'b2001050', 'b2001210', 'b2001220', 'b2001300', 'b2001310', 'b2001330', 'b2001340', 'b2001510', 'b2001530', 'b2001550', 'b2001570', 'b2001590', 'b2001710', 'b2001720', 'b2001750', ] jt.Compat = { 'p11380000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12000000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12230000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12640000': ['b2001210', 'b2001220', 'b2001310', 'b2001330', 'b2001340', 'b2001590', ], 'p13120000': ['b2001210', 'b2001220', 'b2001310', 'b2001330', 'b2001340', 'b2001590', ], 'p13550000': ['b2001050', 'b2001570', ], 'p13680000': ['b2001300', ], 'p13690000': ['b2001300', ], 'p60608051': ['b2001710', 'b2001720', 'b2001750', ], 'p60615162': ['b2001710', ], 'p60717R51': ['b2001710', 'b2001720', 'b2001750', ], 'p60718052': ['b2001710', 'b2001720', 'b2001750', ], } jt.BlckMach = { 'b2001050' : ['m2001050', 'm2001070'], 'b2001210' : ['m2001210', 'm2001230'], 'b2001220' : ['m2001220', 'm2001240'], 'b2001300' : ['m2001300', 'm2001320'], 'b2001310' : ['m2001310'], 'b2001330' : ['m2001330'], 'b2001340' : ['m2001340'], 'b2001510' : ['m2001510', 'm2001520'], 'b2001530' : ['m2001530', 'm2001540'], 'b2001550' : ['m2001550', 'm2001560'], 'b2001570' : ['m2001570', 'm2001580'], 'b2001590' : ['m2001590', 'm2001600'], 'b2001710' : ['m2001710', 'm2001730'], 'b2001720' : ['m2001720', 'm2001740'], 'b2001750' : ['m2001750', 'm2001760'], } jt.Mach = [] for i in jt.BlckMach.values(): for m in i: jt.Mach.append(m) jt.SetUpCost = .070000 jt.VariableCost = 1.188298 jt.HoldingCost = 0.100000 jt.BacklogCost = 1000000 setuptime = 3.5 jt.SetUpTime = {} for p in jt.Prod: for b in jt.Compat[p]: for t in jt.Period: jt.SetUpTime[p,b,t] = setuptime jt.TotalWorkHours = { 1: 21 * 8, 2: 19 * 8, 3: 21 * 8, 4: 20 * 8, 5: 21 * 8, 6: 20 * 8, 7: 21 * 8, 8: 21 * 8, 9: 20 * 8, 10: 21 * 8, 11: 20 * 8, 12: 21 * 8, } jt.Unavailable = { ('b2001050',1) : 0 * 8, ('b2001210',1) : 0 * 8, ('b2001220',1) : 0 * 8, ('b2001300',2) : 0 * 8, ('b2001310',2) : 0 * 8, ('b2001330',2) : 0 * 8, ('b2001340',3) : 0 * 8, ('b2001510',3) : 0 * 8, ('b2001530',3) : 0 * 8, ('b2001550',4) : 0 * 8, ('b2001570',4) : 0 * 8, ('b2001590',4) : 0 * 8, ('b2001710',5) : 0 * 8, ('b2001720',5) : 0 * 8, ('b2001750',5) : 0 * 8, } jt.WorkHours = {} for b in jt.Blck: for t in jt.Period: jt.WorkHours[b,t] = jt.TotalWorkHours[t] if (b,t) in jt.Unavailable.keys(): jt.WorkHours[b,t] -= jt.Unavailable[b,t] jt.MaxRate = {} # 'b2001570': (9.55878 + 14.674) * 21./8, # 'b2001590': (0 + 0) * 21./8, # 'b2001710': (3.548335 + 3.548335) * 21./8, # 'b2001720': (3.47592 + 3.47592) * 21./8, # 'b2001750': (3.809029 + 3.809029) * 21./8, # } # for p in jt.Prod: # for m in jt.Compat[p]: # jt.MaxRate[(p,m)] = Spd[m] jt.iRate = {} # production rate (M units/h) (values extracted considering 8 working hours/day) for p in jt.Prod: jt.iRate[p,'m2001050'] = 1.1 * 5.126982 / 8. jt.iRate[p,'m2001070'] = 1.1 * 5.126982 / 8. jt.iRate[p,'m2001210'] = 1.1 * 0 / 8. jt.iRate[p,'m2001230'] = 1.1 * 0 / 8. jt.iRate[p,'m2001220'] = 1.1 * 0 / 8. jt.iRate[p,'m2001240'] = 1.1 * 0 / 8. jt.iRate[p,'m2001300'] = 1.1 * 5.720785 / 8. jt.iRate[p,'m2001320'] = 1.1 * 5.720785 / 8. jt.iRate[p,'m2001310'] = 1.1 * 5.807683 / 8. jt.iRate[p,'m2001330'] = 1.1 * 5.807683 / 8. jt.iRate[p,'m2001340'] = 1.1 * 5.807683 / 8. jt.iRate[p,'m2001510'] = 1.1 * 9.196705 / 8. jt.iRate[p,'m2001520'] = 1.1 * 15.07 / 8. jt.iRate[p,'m2001530'] = 1.1 * 9.84844 / 8. jt.iRate[p,'m2001540'] = 1.1 * 15.18 / 8. jt.iRate[p,'m2001550'] = 1.1 * 9.674644 / 8. jt.iRate[p,'m2001560'] = 1.1 * 15.356 / 8. jt.iRate[p,'m2001570'] = 1.1 * 9.55878 / 8. jt.iRate[p,'m2001580'] = 1.1 * 14.674 / 8. jt.iRate[p,'m2001590'] = 1.1 * 0 / 8. jt.iRate[p,'m2001600'] = 1.1 * 0 / 8. jt.iRate[p,'m2001710'] = 1.1 * 3.548335 / 8. jt.iRate[p,'m2001730'] = 1.1 * 3.548335 / 8. jt.iRate[p,'m2001720'] = 1.1 * 3.47592 / 8. jt.iRate[p,'m2001740'] = 1.1 * 3.47592 / 8. jt.iRate[p,'m2001750'] = 1.1 * 3.809029 / 8. jt.iRate[p,'m2001760'] = 1.1 * 3.809029 / 8. jt.MaxRate = {} for p in jt.Prod: for b in jt.Compat[p]: jt.MaxRate[p,b] = sum([jt.iRate[p,m] for m in jt.BlckMach[b]]) for (p,b) in jt.MaxRate.keys(): if jt.MaxRate[p,b] == 0.: jt.Compat[p].remove(b) Dem = { 'p11380000': 1023, 'p12000000': 518, 'p12230000': 513, 'p12640000': 272, 'p13120000': 98, 'p13550000': 220, 'p13680000': 93, 'p13690000': 70, 'p60608051': 30, 'p60615162': 11, 'p60717R51': 4, 'p60718052': 400, } jt.mk_const_demand(Dem) # jt.mk_rnd_demand(Dem) ###################################################################### ###################################################################### ###################################################################### def mk_rnd_data(T, nprod, setup_, variable_, holding_, backlog_, time_): """make a random instance, based on fri-jt data, but with different number of periods, products, ... setup_ -> maximal setup cost variable_ -> variable holding_ backlog_ time_ -> maximal setup time """ rnd = fridata() rnd.HoldingCost = holding_ rnd.BacklogCost = backlog_ setuptime = time_ setupcost = setup_ variablecost = variable_ rnd.T = T rnd.Period = range(1,rnd.T+1) rnd.Prod = [ 'p11380000', 'p12000000', 'p12230000', 'p12640000', 'p13120000', 'p13550000', 'p13680000', 'p13690000', 'p60608051', 'p60615162', 'p60717R51', 'p60718052', ] rnd.Prod = rnd.Prod[:nprod] # print 'prod:', rnd.Prod AllBlck = [ 'b2001050', 'b2001210', 'b2001220', 'b2001300', 'b2001310', 'b2001330', 'b2001340', 'b2001510', 'b2001530', 'b2001550', 'b2001570', 'b2001590', 'b2001710', 'b2001720', 'b2001750', ] rnd.Compat = { 'p11380000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12000000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12230000': ['b2001050', 'b2001510', 'b2001530', 'b2001550', 'b2001570', ], 'p12640000': ['b2001210', 'b2001220', 'b2001310', 'b2001330', 'b2001340', 'b2001590', ], 'p13120000': ['b2001210', 'b2001220', 'b2001310', 'b2001330', 'b2001340', 'b2001590', ], 'p13550000': ['b2001050', 'b2001570', ], 'p13680000': ['b2001300', ], 'p13690000': ['b2001300', ], 'p60608051': ['b2001710', 'b2001720', 'b2001750', ], 'p60615162': ['b2001710', ], 'p60717R51': ['b2001710', 'b2001720', 'b2001750', ], 'p60718052': ['b2001710', 'b2001720', 'b2001750', ], } # make set of used blocks Blck = Set([]) for p in rnd.Prod: for b in AllBlck: if b in rnd.Compat[p]: Blck.add(b) rnd.Blck = list(Blck) assert rnd.Blck != [] # print 'blck:', rnd.Blck # remove unused blocks from Compat for key in rnd.Compat.keys(): for compat in rnd.Compat[key]: if compat not in rnd.Blck: rnd.Compat[key].remove(compat) # print 'compat', rnd.Compat rnd.BlckMach = { 'b2001050' : ['m2001050', 'm2001070'], 'b2001210' : ['m2001210', 'm2001230'], 'b2001220' : ['m2001220', 'm2001240'], 'b2001300' : ['m2001300', 'm2001320'], 'b2001310' : ['m2001310'], 'b2001330' : ['m2001330'], 'b2001340' : ['m2001340'], 'b2001510' : ['m2001510', 'm2001520'], 'b2001530' : ['m2001530', 'm2001540'], 'b2001550' : ['m2001550', 'm2001560'], 'b2001570' : ['m2001570', 'm2001580'], 'b2001590' : ['m2001590', 'm2001600'], 'b2001710' : ['m2001710', 'm2001730'], 'b2001720' : ['m2001720', 'm2001740'], 'b2001750' : ['m2001750', 'm2001760'], } keys = rnd.BlckMach.keys() for k in keys: if k not in rnd.Blck: rnd.BlckMach.pop(k) # print 'blckmach', rnd.BlckMach rnd.Mach = [] for i in rnd.BlckMach.values(): for m in i: rnd.Mach.append(m) rnd.SetUpTime = {} rnd.SetUpCost = {} rnd.VariableCost = {} for p in rnd.Prod: for b in rnd.Compat[p]: for t in rnd.Period: rnd.SetUpTime[p,b,t] = setuptime * random.random() rnd.SetUpCost[p,b,t] = setupcost * random.random() rnd.VariableCost[p,b,t] = variablecost * random.random() rnd.TotalWorkHours = { 1: 21 * 8, 2: 19 * 8, 3: 21 * 8, 4: 20 * 8, 5: 21 * 8, 6: 20 * 8, 7: 21 * 8, 8: 21 * 8, 9: 20 * 8, 10: 21 * 8, 11: 20 * 8, 12: 21 * 8, } rnd.Unavailable = { ('b2001050',1) : 0 * 8, ('b2001210',1) : 0 * 8, ('b2001220',1) : 0 * 8, ('b2001300',2) : 0 * 8, ('b2001310',2) : 0 * 8, ('b2001330',2) : 0 * 8, ('b2001340',3) : 0 * 8, ('b2001510',3) : 0 * 8, ('b2001530',3) : 0 * 8, ('b2001550',4) : 0 * 8, ('b2001570',4) : 0 * 8, ('b2001590',4) : 0 * 8, ('b2001710',5) : 0 * 8, ('b2001720',5) : 0 * 8, ('b2001750',5) : 0 * 8, } rnd.WorkHours = {} for b in rnd.Blck: for t in rnd.Period: rnd.WorkHours[b,t] = rnd.TotalWorkHours[t] if (b,t) in rnd.Unavailable.keys(): rnd.WorkHours[b,t] -= rnd.Unavailable[b,t] rnd.MaxRate = {} # 'b2001570': (9.55878 + 14.674) * 21./8, # 'b2001590': (0 + 0) * 21./8, # 'b2001710': (3.548335 + 3.548335) * 21./8, # 'b2001720': (3.47592 + 3.47592) * 21./8, # 'b2001750': (3.809029 + 3.809029) * 21./8, # } # for p in rnd.Prod: # for m in rnd.Compat[p]: # rnd.MaxRate[(p,m)] = Spd[m] rnd.iRate = {} # production rate (M units/h) (values extracted considering 8 working hours/day) for p in rnd.Prod: rnd.iRate[p,'m2001050'] = random.random()* 10 / 8. rnd.iRate[p,'m2001070'] = random.random()* 10 / 8. rnd.iRate[p,'m2001210'] = random.random()* 10 / 8. rnd.iRate[p,'m2001230'] = random.random()* 10 / 8. rnd.iRate[p,'m2001220'] = random.random()* 10 / 8. rnd.iRate[p,'m2001240'] = random.random()* 10 / 8. rnd.iRate[p,'m2001300'] = random.random()* 10 / 8. rnd.iRate[p,'m2001320'] = random.random()* 10 / 8. rnd.iRate[p,'m2001310'] = random.random()* 10 / 8. rnd.iRate[p,'m2001330'] = random.random()* 10 / 8. rnd.iRate[p,'m2001340'] = random.random()* 10 / 8. rnd.iRate[p,'m2001510'] = random.random()* 10 / 8. rnd.iRate[p,'m2001520'] = random.random()* 10 / 8. rnd.iRate[p,'m2001530'] = random.random()* 10 / 8. rnd.iRate[p,'m2001540'] = random.random()* 10 / 8. rnd.iRate[p,'m2001550'] = random.random()* 10 / 8. rnd.iRate[p,'m2001560'] = random.random()* 10 / 8. rnd.iRate[p,'m2001570'] = random.random()* 10 / 8. rnd.iRate[p,'m2001580'] = random.random()* 10 / 8. rnd.iRate[p,'m2001590'] = random.random()* 10 / 8. rnd.iRate[p,'m2001600'] = random.random()* 10 / 8. rnd.iRate[p,'m2001710'] = random.random()* 10 / 8. rnd.iRate[p,'m2001730'] = random.random()* 10 / 8. rnd.iRate[p,'m2001720'] = random.random()* 10 / 8. rnd.iRate[p,'m2001740'] = random.random()* 10 / 8. rnd.iRate[p,'m2001750'] = random.random()* 10 / 8. rnd.iRate[p,'m2001760'] = random.random()* 10 / 8. rnd.MaxRate = {} for p in rnd.Prod: for b in rnd.Compat[p]: rnd.MaxRate[p,b] = sum([rnd.iRate[p,m] for m in rnd.BlckMach[b]]) for (p,b) in rnd.MaxRate.keys(): if rnd.MaxRate[p,b] == 0.: rnd.Compat[p].remove(b) Dem = { 'p11380000': 0.1 * 1023, 'p12000000': 0.1 * 518, 'p12230000': 0.1 * 513, 'p12640000': 0.1 * 272, 'p13120000': 0.1 * 98, 'p13550000': 0.1 * 220, 'p13680000': 0.1 * 93, 'p13690000': 0.1 * 70, 'p60608051': 0.1 * 30, 'p60615162': 0.1 * 11, 'p60717R51': 0.1 * 4, 'p60718052': 0.1 * 400, } rnd.mk_const_demand(Dem) # rnd.mk_rnd_demand(Dem) return rnd rnd = mk_rnd_data(12, 12, 10., 0.5, 0.1, 1., 3.5) import pickle try: tmp = pickle.load(open('fridata.p')) inst = tmp print "loaded 'inst' from 'fridata.p'" except Exception: inst = [] setup=10.; variable=.05; holding=0.1; backlog=1.; time=3.5 for n in [2, 3, 4, 5, 6, 7, 8, 9, 10, 12]: T=n; nprod=n; rnd = mk_rnd_data(T, nprod, setup, variable, holding, backlog, time) rnd.mkampl('fri-inst-%02d.dat' % n) inst.append(rnd) print "produced 'fri-rnd-%02d.dat'" % n pickle.dump(inst,open('fridata.p','w')) print "saved all instances in 'fridata.p'" if __name__ == "__main__": random.seed(1) toy.mkampl('fri-toy.dat') ### cut can be: , {('b2',3):10}) print "produced 'fri-toy.dat'" # for b in toy.Blck: # print b, "can produce", [p for p in toy.Compat.keys() if b in toy.Compat[p]] jt.mkampl('fri-jt.dat') print "produced 'fri-jt.dat'" # for b in jt.Blck: # print b, "can produce", [p for p in jt.Compat.keys() if b in jt.Compat[p]] T=12; nprod=12; setup=10.; variable=.5; holding=0.1; backlog=1.; time=3.5 rnd = mk_rnd_data(T, nprod, setup, variable, holding, backlog, time) rnd.mkampl('fri-rnd.dat') print "produced 'fri-rnd.dat'" # for b in rnd.Blck: # print b, "can produce", [p for p in rnd.Compat.keys() if b in rnd.Compat[p]] for n in [2, 3, 4, 5, 6, 7, 8, 9, 10, 12]: T=n; nprod=n; rnd = mk_rnd_data(T, nprod, setup, variable, holding, backlog, time) rnd.mkampl('fri-rnd-%02d.dat' % n) print "produced 'fri-rnd-%02d.dat'" % n