예제 #1
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
예제 #2
0
 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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
 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
예제 #8
0
 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
예제 #9
0
 def makechromosome(self):
     pages = solver_tools.Pagination(capacity)
     tiles = solver_tools.Batch(refTiles)
     firstFit(pages, tiles.getShuffledClone())
     self.length = len(pages)
     return pages
예제 #10
0
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