Exemplo n.º 1
0
def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
  """This recursive function does the following with an existing tiling TSoFar:
     
     * For each 4-tuple (Xdim,Ydim,job,rjob) in Jobs, the non-rotated 'job' is selected
     
     * For the non-rotated job, the list of valid add-points is found

     * For each valid add-point, the job is placed at this point in a new,
       cloned tiling.

     * The function then calls its recursively with the remaining list of
       jobs.

     * The rotated job is then selected and the list of valid add-points is
       found. Again, for each valid add-point the job is placed there in
       a new, cloned tiling.

     * Once again, the function calls itself recursively with the remaining
       list of jobs.

     * The best tiling encountered from all recursive calls is returned.

     If TSoFar is None it means this combination of jobs is not tileable.

     The side-effect of this function is to set _TBestTiling and _TBestScore
     to the best tiling encountered so far. _TBestTiling could be None if
     no valid tilings have been found so far.
  """
  global _StartTime, _CkpointTime, _Placements, _TBestTiling, _TBestScore, _Permutations, _PrintStats

  if not TSoFar:
    return (None, float(sys.maxint))

  if not Jobs:
    # Update the best tiling and score. If the new tiling matches
    # the best score so far, compare on number of corners, trying to
    # minimize them.
    score = TSoFar.area()

    if score < _TBestScore:
      _TBestTiling,_TBestScore = TSoFar,score
    elif score == _TBestScore:
      if TSoFar.corners() < _TBestTiling.corners():
        _TBestTiling,_TBestScore = TSoFar,score

    _Placements += 1
    if firstAddPoint:
      _Permutations += 1
    return

  xspacing = cfg['xspacing']
  yspacing = cfg['yspacing']

  minInletSize = tiling.minDimension(Jobs)
  TSoFar.removeInlets(minInletSize)

  for job_ix in range(len(Jobs)):
    # Pop off the next job and construct remaining_jobs, a sub-list
    # of Jobs with the job we've just popped off excluded.
    Xdim,Ydim,job,rjob = Jobs[job_ix]
    remaining_jobs = Jobs[:job_ix]+Jobs[job_ix+1:]

    if 0:
      print "Level %d (%s)" % (level, job.name)
      TSoFar.joblist()
      for J in remaining_jobs:
          print J[2].name, ", ",
      print
      print '-'*75

    # Construct add-points for the non-rotated and rotated job.
    # As an optimization, do not construct add-points for the rotated
    # job if the job is a square (duh).
    addpoints1 = TSoFar.validAddPoints(Xdim+xspacing,Ydim+yspacing)     # unrotated job
    if Xdim != Ydim:
      addpoints2 = TSoFar.validAddPoints(Ydim+xspacing,Xdim+yspacing)   # rotated job
    else:
      addpoints2 = []

    # Recursively construct tilings for the non-rotated job and
    # update the best-tiling-so-far as we do so.
    if addpoints1:
      for ix in addpoints1:
        # Clone the tiling we're starting with and add the job at this
        # add-point.
        T = TSoFar.clone()
        T.addJob(ix, Xdim+xspacing, Ydim+yspacing, job)

        # Recursive call with the remaining jobs and this new tiling. The
        # point behind the last parameter is simply so that _Permutations is
        # only updated once for each permutation, not once per add-point.
        # A permutation is some ordering of jobs (N! choices) and some
        # ordering of non-rotated and rotated within that ordering (2**N
        # possibilities per ordering).
        _tile_search1(remaining_jobs, T, firstAddPoint and ix==addpoints1[0])
    elif firstAddPoint:
      # Premature prune due to not being able to put this job anywhere. We
      # have pruned off 2^M permutations where M is the length of the remaining
      # jobs.
      _Permutations += 2L**len(remaining_jobs)

    if addpoints2:
      for ix in addpoints2:
        # Clone the tiling we're starting with and add the job at this
        # add-point. Remember that the job is rotated so swap X and Y
        # dimensions.
        T = TSoFar.clone()
        T.addJob(ix, Ydim+xspacing, Xdim+yspacing, rjob)

        # Recursive call with the remaining jobs and this new tiling.
        _tile_search1(remaining_jobs, T, firstAddPoint and ix==addpoints2[0])
    elif firstAddPoint:
      # Premature prune due to not being able to put this job anywhere. We
      # have pruned off 2^M permutations where M is the length of the remaining
      # jobs.
      _Permutations += 2L**len(remaining_jobs)

    # If we've been at this for 3 seconds, print some status information
    if _PrintStats and time.time() > _CkpointTime:
      printTilingStats()
      
      # Check for timeout - changed to file config
      if (config.Config['searchtimeout'] > 0) and ((time.time() - _StartTime) > config.Config['searchtimeout']):
        raise KeyboardInterrupt 
        
    gerbmerge.updateGUI("Performing automatic layout...")        
Exemplo n.º 2
0
def _tile_search2(Jobs, X, Y, cfg=config.Config):
    global _CkpointTime, _Placements, _TBestTiling, _TBestScore

    r = random.Random()
    N = len(Jobs)

    # M is the number of jobs that will be placed randomly.
    # N-M is the number of jobs that will be searched exhaustively.
    M = N - config.RandomSearchExhaustiveJobs
    M = max(M, 0)

    xspacing = cfg['xspacing']
    yspacing = cfg['yspacing']

    # Must escape with Ctrl-C
    while 1:
        T = tiling.Tiling(X, Y)
        joborder = r.sample(range(N), N)

        minInletSize = tiling.minDimension(Jobs)

        for ix in joborder[:M]:
            Xdim, Ydim, job, rjob = Jobs[ix]

            T.removeInlets(minInletSize)

            if r.choice([0, 1]):
                addpoints = T.validAddPoints(Xdim + xspacing, Ydim + yspacing)
                if not addpoints:
                    break

                pt = r.choice(addpoints)
                T.addJob(pt, Xdim + xspacing, Ydim + yspacing, job)
            else:
                addpoints = T.validAddPoints(Ydim + xspacing, Xdim + yspacing)
                if not addpoints:
                    break

                pt = r.choice(addpoints)
                T.addJob(pt, Ydim + xspacing, Xdim + yspacing, rjob)
        else:
            # Do exhaustive search on remaining jobs
            if N - M:
                remainingJobs = []
                for ix in joborder[M:]:
                    remainingJobs.append(Jobs[ix])

                tilesearch1.initialize(0)
                tilesearch1._tile_search1(remainingJobs, T, 1)
                T = tilesearch1.bestTiling()

            if T:
                score = T.area()

                if score < _TBestScore:
                    _TBestTiling, _TBestScore = T, score
                elif score == _TBestScore:
                    if T.corners() < _TBestTiling.corners():
                        _TBestTiling, _TBestScore = T, score

        _Placements += 1

        # If we've been at this for 3 seconds, print some status information
        if time.time() > _CkpointTime:
            printTilingStats()

            # Check for timeout - changed to file config
            if (config.Config['searchtimeout'] > 0) and (
                (time.time() - _StartTime) > config.Config['searchtimeout']):
                raise KeyboardInterrupt

        gerbmerge.updateGUI("Performing automatic layout...")
def _tile_search2(Jobs, X, Y, cfg=config.Config):
  global _CkpointTime, _Placements, _TBestTiling, _TBestScore

  r = random.Random()
  N = len(Jobs)

  # M is the number of jobs that will be placed randomly.
  # N-M is the number of jobs that will be searched exhaustively.
  M = N - config.RandomSearchExhaustiveJobs
  M = max(M,0)

  xspacing = cfg['xspacing']
  yspacing = cfg['yspacing']
  
  # Must escape with Ctrl-C
  while 1:
    T = tiling.Tiling(X,Y)
    joborder = r.sample(range(N), N)

    minInletSize = tiling.minDimension(Jobs)

    for ix in joborder[:M]:
      Xdim,Ydim,job,rjob = Jobs[ix]
      
      T.removeInlets(minInletSize)

      if r.choice([0,1]):
        addpoints = T.validAddPoints(Xdim+xspacing,Ydim+yspacing)
        if not addpoints:
          break

        pt = r.choice(addpoints)
        T.addJob(pt, Xdim+xspacing, Ydim+yspacing, job)
      else:
        addpoints = T.validAddPoints(Ydim+xspacing,Xdim+yspacing)
        if not addpoints:
          break

        pt = r.choice(addpoints)
        T.addJob(pt, Ydim+xspacing, Xdim+yspacing, rjob)
    else:
      # Do exhaustive search on remaining jobs
      if N-M:
        remainingJobs = []
        for ix in joborder[M:]:
          remainingJobs.append(Jobs[ix])

        tilesearch1.initialize(0)
        tilesearch1._tile_search1(remainingJobs, T, 1)
        T = tilesearch1.bestTiling()

      if T:
        score = T.area()

        if score < _TBestScore:
          _TBestTiling,_TBestScore = T,score
        elif score == _TBestScore:
          if T.corners() < _TBestTiling.corners():
            _TBestTiling,_TBestScore = T,score

    _Placements += 1
      
    # If we've been at this for 3 seconds, print some status information
    if time.time() > _CkpointTime:
      printTilingStats()
      
      # Check for timeout - changed to file config
      if (config.Config['searchtimeout'] > 0) and ((time.time() - _StartTime) > config.Config['searchtimeout']):
        raise KeyboardInterrupt 
        
    gerbmerge.updateGUI("Performing automatic layout...")
Exemplo n.º 4
0
def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
  """This recursive function does the following with an existing tiling TSoFar:
     
     * For each 4-tuple (Xdim,Ydim,job,rjob) in Jobs, the non-rotated 'job' is selected
     
     * For the non-rotated job, the list of valid add-points is found

     * For each valid add-point, the job is placed at this point in a new,
       cloned tiling.

     * The function then calls its recursively with the remaining list of
       jobs.

     * The rotated job is then selected and the list of valid add-points is
       found. Again, for each valid add-point the job is placed there in
       a new, cloned tiling.

     * Once again, the function calls itself recursively with the remaining
       list of jobs.

     * The best tiling encountered from all recursive calls is returned.

     If TSoFar is None it means this combination of jobs is not tileable.

     The side-effect of this function is to set _TBestTiling and _TBestScore
     to the best tiling encountered so far. _TBestTiling could be None if
     no valid tilings have been found so far.
  """
  global _StartTime, _CkpointTime, _Placements, _TBestTiling, _TBestScore, _Permutations, _PrintStats

  if not TSoFar:
    return (None, float(sys.maxint))

  if not Jobs:
    # Update the best tiling and score. If the new tiling matches
    # the best score so far, compare on number of corners, trying to
    # minimize them.
    score = TSoFar.area()

    if score < _TBestScore:
      _TBestTiling,_TBestScore = TSoFar,score
    elif score == _TBestScore:
      if TSoFar.corners() < _TBestTiling.corners():
        _TBestTiling,_TBestScore = TSoFar,score

    _Placements += 1
    if firstAddPoint:
      _Permutations += 1
    return

  xspacing = cfg['xspacing']
  yspacing = cfg['yspacing']

  minInletSize = tiling.minDimension(Jobs)
  TSoFar.removeInlets(minInletSize)

  for job_ix in range(len(Jobs)):
    # Pop off the next job and construct remaining_jobs, a sub-list
    # of Jobs with the job we've just popped off excluded.
    Xdim,Ydim,job,rjob = Jobs[job_ix]
    remaining_jobs = Jobs[:job_ix]+Jobs[job_ix+1:]

    if 0:
      print "Level %d (%s)" % (level, job.name)
      TSoFar.joblist()
      for J in remaining_jobs:
          print J[2].name, ", ",
      print
      print '-'*75

    # Construct add-points for the non-rotated and rotated job.
    # As an optimization, do not construct add-points for the rotated
    # job if the job is a square (duh).
    addpoints1 = TSoFar.validAddPoints(Xdim+xspacing,Ydim+yspacing)     # unrotated job
    if Xdim != Ydim:
      addpoints2 = TSoFar.validAddPoints(Ydim+xspacing,Xdim+yspacing)   # rotated job
    else:
      addpoints2 = []

    # Recursively construct tilings for the non-rotated job and
    # update the best-tiling-so-far as we do so.
    if addpoints1:
      for ix in addpoints1:
        # Clone the tiling we're starting with and add the job at this
        # add-point.
        T = TSoFar.clone()
        T.addJob(ix, Xdim+xspacing, Ydim+yspacing, job)

        # Recursive call with the remaining jobs and this new tiling. The
        # point behind the last parameter is simply so that _Permutations is
        # only updated once for each permutation, not once per add-point.
        # A permutation is some ordering of jobs (N! choices) and some
        # ordering of non-rotated and rotated within that ordering (2**N
        # possibilities per ordering).
        _tile_search1(remaining_jobs, T, firstAddPoint and ix==addpoints1[0])
    elif firstAddPoint:
      # Premature prune due to not being able to put this job anywhere. We
      # have pruned off 2^M permutations where M is the length of the remaining
      # jobs.
      _Permutations += 2L**len(remaining_jobs)

    if addpoints2:
      for ix in addpoints2:
        # Clone the tiling we're starting with and add the job at this
        # add-point. Remember that the job is rotated so swap X and Y
        # dimensions.
        T = TSoFar.clone()
        T.addJob(ix, Ydim+xspacing, Xdim+yspacing, rjob)

        # Recursive call with the remaining jobs and this new tiling.
        _tile_search1(remaining_jobs, T, firstAddPoint and ix==addpoints2[0])
    elif firstAddPoint:
      # Premature prune due to not being able to put this job anywhere. We
      # have pruned off 2^M permutations where M is the length of the remaining
      # jobs.
      _Permutations += 2L**len(remaining_jobs)

    # If we've been at this for 3 seconds, print some status information
    if _PrintStats and time.time() > _CkpointTime:
      printTilingStats()
      
      # Check for timeout
      if (config.SearchTimeout > 0) and (time.time() - _StartTime > config.SearchTimeout):
        raise KeyboardInterrupt 
        
    gerbmerge.updateGUI("Performing automatic layout...")