def makechromosome(self): pages = solver_tools.Pagination(capacity) tiles = solver_tools.Batch(refTiles) firstFit(pages, tiles.getShuffledClone()) result = [pages.pageIndexOfTile(tile) for tile in tiles] Individual.maxPageCount = max( max(result) + 1, Individual.maxPageCount) return result
def copy(self): twinPagination = solver_tools.Pagination(capacity) for page in self.chromosome: twinPagination.newPage(page) twin = Individual(twinPagination) twin.length = self.length twin.score = self.score # print "twin", twin.score return twin
def run(testSet): pages = solver_tools.Pagination(testSet["capacity"], name) tiles = solver_tools.Batch(testSet["tiles"]) for tile in tiles: for page in pages: if tile.canFitIn(page): page.add(tile) break else: pages.newPage(tile) return pages
def run(testSet, maxPageCount=None, knownPaginations=[], **kargs): class Individual(genetic.Individual): optimization = "MINIMIZE" separator = ',' maxPageCount = 0 def makechromosome(self): pages = solver_tools.Pagination(capacity) tiles = solver_tools.Batch(refTiles) firstFit(pages, tiles.getShuffledClone()) result = [pages.pageIndexOfTile(tile) for tile in tiles] Individual.maxPageCount = max( max(result) + 1, Individual.maxPageCount) return result def evaluate(self, optimum=None): symbolsOnPages = [[] for _ in xrange(Individual.maxPageCount)] for (tileIndex, pageIndex) in enumerate(self.chromosome): symbolsOnPages[pageIndex].extend(refTiles[tileIndex]) page_costs = [len(set(symbols)) for symbols in symbolsOnPages] if max(page_costs) > capacity: self.score = invalidPenalty + sum( max(0, n - capacity) for n in page_costs) else: for i in xrange(Individual.maxPageCount - 1, -1, -1): if page_costs[i]: self.score = page_costs[i] + i * capacity break def mutate(self, gene): self.chromosome[gene] = random.randrange(Individual.maxPageCount) # tiles = solver_tools.Batch(testSet["tiles"]) capacity = testSet["capacity"] refTiles = solver_tools.Batch(testSet["tiles"]) Individual.length = len(refTiles) invalidPenalty = capacity * testSet["tileCount"] # if knownPaginations: # maxPageCount = min(len(knownPagination) for knownPagination in knownPaginations if knownPagination.isValid()) # for (knownPaginationIndex,knownPagination) in enumerate(knownPaginations): # if knownPagination.isValid() and len(knownPagination) == maxPageCount: # for (tileIndex,tile) in enumerate(tiles): # env.population[knownPaginationIndex].chromosome[tileIndex] = knownPagination.pageIndexOfTile(tile) env = genetic.Environment(Individual, **kargs) env.run() pages = solver_tools.Pagination(testSet["capacity"], name) for _ in range(max(env.best.chromosome) + 1): pages.newPage() for (tileIndex, pageIndex) in enumerate(env.best.chromosome): pages[pageIndex].add(refTiles[tileIndex]) return pages
def run(testSet, quiet=True): pages = solver_tools.Pagination(testSet["capacity"], '' if quiet else name) pool = [solver_tools.Tile(tile) for tile in testSet["tiles"]] pool.sort(key=lambda tile: tile.size, reverse=True) for tile in pool: tile.forbiddenPages = [] tile = pool.pop(0) # print "Place tile %s on empty page" % tile pages.newPage(tile) while pool: tile = pool.pop(0) # print "Forbidden pages: %s" % str([pages.index(page) for page in tile.forbiddenPages]) candidates = set(pages).difference(tile.forbiddenPages) if not candidates: # print "Place tile %s on empty page %s " % (tile,len(pages)) pages.newPage(tile) continue costs = ((tile.weightedCostIn(page), page) for page in candidates) (bestWeightedCost, bestPage) = min(costs, key=lambda x: x[0]) if bestWeightedCost == len(tile): # print "Place tile %s on empty page %s " % (tile,len(pages)) pages.newPage(tile) continue # print "Add tile %s on page %s" % (tile,pages.index(bestPage)) bestPage.add(tile) while bestPage.cost > pages.capacity: # print "Page %s exceeded!" % pages.index(bestPage) minEfficiency = min(bestPage.actualEfficiencies) maxEfficiency = max(bestPage.actualEfficiencies) # print (minEfficiency,maxEfficiency) if minEfficiency == maxEfficiency: break tile = bestPage[bestPage.actualEfficiencies.index(minEfficiency)] # print "Remove tile %s from page %s" % (tile,pages.index(bestPage)) bestPage.remove(tile) tile.forbiddenPages.append(bestPage) pool.append(tile) # print "Page %s not saturated." % pages.index(bestPage) for i in range(len(pages) - 1, -1, -1): if pages[i].cost > pages.capacity: pool.extend(pages.pop(i)[:]) for tile in pool: for page in pages: if tile.canFitIn(page): page.add(tile) break else: pages.newPage(tile) # print pages return pages
def run(testSet): pages = solver_tools.Pagination(testSet["capacity"], name) tiles = solver_tools.Batch(testSet["tiles"]) for tile in tiles: candidates = [page for page in pages if tile.canFitIn(page)] if candidates: (minWeightedCost, bestPage) = min( (tile.weightedCostIn(page), page) for page in candidates) if minWeightedCost < len(tile): bestPage.add(tile) else: pages.newPage(tile) else: pages.newPage(tile) return pages
def newInstance(self, testSet, name, testSetCount): print "Solving %s (%s)" % (name, testSetCount) self.filename = name if "solvers" not in testSet: testSet["solvers"] = {} if testSet["pageCount"]: algoName = re.sub(" \[.+", "", testSet.get("approximation", "given")) self.instancePaginations = [ solver_tools.Pagination(testSet["capacity"], algoName) ] print "%(pageCount)s pages (current best)" % testSet for page in testSet["paginations"]: self.instancePaginations[-1].newPage( [testSet["tiles"][tileIndex] for tileIndex in page]) testSet["solvers"][algoName] = testSet["pageCount"] else: self.instancePaginations = [] self.testSet = testSet
def mate(p1, left1, right1, p2, left2, right2): pages = solver_tools.Pagination(capacity) medianTiles = set(tile for i in xrange(left2, right2) for tile in p2.chromosome[i]) for i in xrange(0, left1): tilesToPlace = p1.chromosome[i].tileSet.difference(medianTiles) if tilesToPlace: pages.newPage(tilesToPlace) for i in xrange(left2, right2): pages.newPage(p2.chromosome[i]) for i in xrange(right1, p1.length): tilesToPlace = p1.chromosome[i].tileSet.difference(medianTiles) if tilesToPlace: pages.newPage(tilesToPlace) pool = list( refTiles.difference(tile for page in pages for tile in page)) pool.sort(key=lambda tile: tile.size, reverse=True) firstFit(pages, pool) child = Individual(pages) child.length = len(pages) return child
def makechromosome(self): pages = solver_tools.Pagination(capacity) tiles = solver_tools.Batch(refTiles) firstFit(pages, tiles.getShuffledClone()) self.length = len(pages) return pages
def run(testSet, **kargs): def mate(p1, left1, right1, p2, left2, right2): pages = solver_tools.Pagination(capacity) medianTiles = set(tile for i in xrange(left2, right2) for tile in p2.chromosome[i]) for i in xrange(0, left1): tilesToPlace = p1.chromosome[i].tileSet.difference(medianTiles) if tilesToPlace: pages.newPage(tilesToPlace) for i in xrange(left2, right2): pages.newPage(p2.chromosome[i]) for i in xrange(right1, p1.length): tilesToPlace = p1.chromosome[i].tileSet.difference(medianTiles) if tilesToPlace: pages.newPage(tilesToPlace) pool = list( refTiles.difference(tile for page in pages for tile in page)) pool.sort(key=lambda tile: tile.size, reverse=True) firstFit(pages, pool) child = Individual(pages) child.length = len(pages) return child class Individual(genetic.Individual): optimization = "MAXIMIZE" separator = ',' def makechromosome(self): pages = solver_tools.Pagination(capacity) tiles = solver_tools.Batch(refTiles) firstFit(pages, tiles.getShuffledClone()) self.length = len(pages) return pages def evaluate(self, optimum=None): # print self.length, self.score = sum((page.weight / maxPageWeight)**2 for page in self.chromosome) / self.length # NB. This should be equivalent to the faster formula: # self.score = sum(page.weight*page.weight for page in self.chromosome)/self.length/maxPageWeight/maxPageWeight # print self.score def mutate(self, gene): tiles = self.chromosome.pop(gene) firstFit(self.chromosome, tiles) self.length = len(self.chromosome) def crossover(self, other): if self is other or self.length < 3 or other.length < 3: return (self, other) left1 = random.randrange(1, self.length - 1) right1 = random.randrange(left1 + 1, self.length) left2 = random.randrange(1, other.length - 1) right2 = random.randrange(left2 + 1, other.length) return mate(self, left1, right1, other, left2, right2), mate(other, left2, right2, self, left1, right1) def copy(self): twinPagination = solver_tools.Pagination(capacity) for page in self.chromosome: twinPagination.newPage(page) twin = Individual(twinPagination) twin.length = self.length twin.score = self.score # print "twin", twin.score return twin capacity = testSet["capacity"] refTiles = solver_tools.Batch(testSet["tiles"]) maxPageWeight = float( sum(sorted(refTiles.weightBySymbol.values(), reverse=True)[:capacity])) pages = solver_tools.Pagination(capacity, name) env = genetic.Environment(Individual, **kargs) min_size_at_start = min(len(x.chromosome) for x in env.population) refTiles = set(tile for tile in refTiles) env.run() for page in env.best.chromosome: pages.newPage(page) return pages