def partswap(self, x, y): # This function swaps parts of two bins with each other openbins = self.findopenbins(y) # Pick two random bins i1 = random.choice(openbins) binitems1 = self.finditemsinbin(x, i1) while len(binitems1) == 1: i1 = random.choice(openbins) binitems1 = self.finditemsinbin(x, i1) i2 = self.getrandsecondbin(i1, x, openbins) # Pick two points to swap after binitems2 = self.finditemsinbin(x, i2) j1 = random.randrange(1, len(binitems1)) j2 = random.randrange(1, len(binitems2)) # Check for violations newbin1 = binitems1[:j1] + binitems2[j2:] newbin2 = binitems2[:j2] + binitems1[j1:] violat1 = constraints.bincheck(newbin1, self.bpp) violat2 = constraints.bincheck(newbin2, self.bpp) if violat1 or violat2 is True: self.splitbin(x, y) # If no violations, swap items: else: for index in newbin1[j1:]: x[i1, index - 1] = 1 x[i2, index - 1] = 0 for index in newbin2[j2:]: x[i2, index - 1] = 1 x[i1, index - 1] = 0 return x, y
def getitemstoswap(self, x, i1, i2): # This function returns two items in bins i1 and i2 that # can be feasibly swapped. # Find items in bin i1 and bin i2 binitems1 = self.finditemsinbin(x, i1) binitems2 = self.finditemsinbin(x, i2) for count1 in range(len(binitems1)): for count2 in range(len(binitems2)): # Select random items in chosen bins # Remember binitems is list of item indices, where index = j + 1 j1 = random.choice(binitems1) - 1 j2 = random.choice(binitems2) - 1 # Check for feasibility newbin1 = list(binitems1) newbin1.remove(j1 + 1) newbin1.append(j2 + 1) check1 = constraints.bincheck(newbin1, self.bpp) newbin2 = list(binitems2) newbin2.remove(j2 + 1) newbin2.append(j1 + 1) check2 = constraints.bincheck(newbin2, self.bpp) # violation if bincheck returns True truthvalue = check1 or check2 # Stop module and return values if found items to swap if truthvalue is False: return j1, j2 return False
def mergebins(self, bpp): # This function merges the two least filled bins into 1 bin. # Note: vlrep has item index in it, which is j + 1 fill_level = np.zeros(len(self.vlrep)) for i in range(len(self.vlrep)): fill_level[i] = len(self.vlrep[i]) binindices = fill_level.argsort()[:2] i1 = binindices[0] i2 = binindices[1] newbin = self.vlrep[i1] + self.vlrep[i2] violation = constraints.bincheck(newbin, bpp) if violation is True: rannum = random.random() if rannum < 0.5: self.partswap(bpp) else: self.splitbin() else: for j in self.vlrep[i2]: self.x[i1, j-1] = 1 for i in range(i2, self.n-1): self.y[i] = self.y[i+1] for j in range(self.n): self.x[i, j] = self.x[i+1, j] self.y[-1] = 0 self.x[-1, :] = 0 self.vlrep[i1].extend(self.vlrep[i2]) del self.vlrep[i2]
def partswap(self, bpp): # This function picks two bins randomly and swaps part of their contents. i1 = random.randrange(len(self.vlrep)) while len(self.vlrep[i1]) == 1: i1 = random.randrange(len(self.vlrep)) i2 = random.randrange(len(self.vlrep)) while i2 == i1 or len(self.vlrep[i2]) == 1: i2 = random.randrange(len(self.vlrep)) j1 = random.randrange(1, len(self.vlrep[i1])) j2 = random.randrange(1, len(self.vlrep[i2])) newbin1 = self.vlrep[i1][:j1] + self.vlrep[i2][j2:] newbin2 = self.vlrep[i2][:j2] + self.vlrep[i1][j1:] violat1 = constraints.bincheck(newbin1, bpp) violat2 = constraints.bincheck(newbin2, bpp) if violat1 or violat2 is True: self.splitbin() else: self.vlrep[i1], self.vlrep[i2] = newbin1, newbin2 for j in self.vlrep[i1][j1:]: self.x[i1, j-1] = 1 self.x[i2, j-1] = 0 for j in self.vlrep[i2][j2:]: self.x[i2, j-1] = 1 self.x[i1, j-1] = 0
def mergebins(self, x, y): # This function merges together the two least filled bins i1, i2 = self.gettwominbins(x, y) old1 = self.finditemsinbin(x, i1) old2 = self.finditemsinbin(x, i2) newbin = old1 + old2 violation = constraints.bincheck(newbin, self.bpp) if violation is True: self.splitbin(x, y) else: # Add items in bin2 to bin1 for index in old2: x[i1, index - 1] = 1 # Move up other bins (overwriting bin2) for i in range(i2, self.n - 1): y[i] = y[i + 1] for j in range(self.n): x[i, j] = x[i + 1, j] # Very last bin will now be empty y[-1] = 0 x[-1, :] = 0 return x, y