Pastebin

Paste #1235: sa2.py

< previous paste - next paste>

Pasted by tdn

Download View as text

import random
import math
import sys
import show_hall
from copy import deepcopy
from time import strftime

seats_file = "seats"
reservations_file = "reservations"

HINT = 5
NOTE = 4
WARN = 3
ERROR= 2
FATAL= 1
NONE = 0
DEBUG_LEVEL = NOTE

def log(msg, level=NOTE):
    if level <= DEBUG_LEVEL:
        #print "%s [%s] %s" % (strftime("%Y-%m-%d %H:%M:%S"), level, msg)
        print msg

class seat:
    def __init__(self, id, score):
        self.sold = 0  # Number of times this seat has been sold
        self.id = id   # Seat id number (written on the seat in the theatre hall)
        self.score = score # 

    def __str__(self):
        return "seat(id:%s,score:%s,sold:%s)" % (self.id, self.score, self.sold)

    def __repr__(self):
        return str(self)

    def pp(self):
        return str(self)

    def __cmp__(self, other):
        return cmp(other.score, self.score)

class hall:
    def __init__(self, rows):
        self.rows = rows

    def __str__(self):
        return "hall(rows:%s)" % self.rows

    def __repr__(self):
        return str(self)

    def pp(self):
        """Return hall as a pretty string"""
        res = "hall("
        for r in self.rows:
            res += "\n  %s" % r.pp()
            
        res += "\n)"
        return res

class row:
    def __init__(self, id, seats):
        self.id = id
        self.seats = []
        self.vacant = 0
        for s in seats:
            self.seats.append(s)
            self.vacant += 1

    def __str__(self):
        return "row(id:%s,seats:%s,vacant:%s)" % (self.id, self.seats, self.vacant)

    def __repr__(self):
        return str(self)

    def next_available(self):
        return len(self.seats) - self.vacant

    def pp(self):
        res = "row( id: %s, vacant: %s, " % (self.id, self.vacant)
        for s in self.seats:
            res += "\n    %s" % (s.pp())
        res += "\n  )"
        return res

class reservation:
    def __init__(self, id, len):
        self.len = len
        self.id = id
        self.seats = []
    
    def __str__(self):
        return "reservation(len:%s,seats:%s)" % (self.len, self.seats)
    
    def __repr__(self):
        return str(self)

    def pp(self):
        res = "reservation(id: %s, len: %s" % (self.id, self.len)
        for s in self.seats:
            res += "\n  %s" % s.pp()
        res += "\n)"
        return res

def load_hall(filename):
    row_num = 0
    seat_num = 0
    rows = []
    for s in open(filename).readlines():
        row_num += 1
        seats = []
        for ss in s.strip().split(","):
            seat_num += 1
            seats.append(seat(seat_num, int(ss)))
        rows.append(row(row_num, seats))
    return hall(rows)
    
def load_reservations(filename):
    reservations = []
    rn = 0
    for r in open(filename).readlines():
        rn += 1
        reservations.append(reservation(rn, int(r.strip())))
    return reservations

def firstfit(hall, reservations):
    for r in reservations:
        log("Finding place for reservation %s with length %s" % (r.id,r.len), HINT)
        for row in hall.rows:
            log("checking row.id %s; len(row.seats) %s; r.len %s" % (row.id, len(row.seats), r.len), HINT)
            if row.vacant >= r.len:
                log("  adding reservation %s to row %s" % (r.id, row.id), HINT)
                log("Placing reservation %s" % reservation, HINT)
                start = row.next_available()
                for x in range(0, r.len):
                    idx = start + x
                    log("  x=%s, start=%s idx=%s" % (x, start, idx), HINT)
                    s = row.seats[idx]
                    s.sold += 1 
                    r.seats.append(s)
                    row.vacant -= 1
                break
    return (hall, reservations)


#============== SIMULATED ANNEALING ===============

def temp(r):
    """yield the temperature to use, given the fraction r of the time budget 
 that has been expended so far"""
    if r == 0:
        return 1
    else: 
        return 1/r

def neighbour(s):
    """Find a neighbour state"""
    (h, reservations) = s
    # Pick a random reservation
    idx = int(rand() * len(reservations))
    r = reservations[idx]
    rsize = len(r.seats)
    #print """We randomly selected reservation %s, with %s seats""" % (r.id, rsize)
    #print r.pp()

    # Pick random row with enough seats
    row = None
    while not row:
        crow = int(rand() * len(h.rows))
        if len(h.rows[crow].seats) >= rsize:
            row = h.rows[crow]
    #print """We will now put this reservation in row %s with size %s""" % (crow, len(h.rows[crow].seats))
    # Pick a random start seat in this row
    new_idx = int(rand() * (len(h.rows[crow].seats)-rsize))
    # Delete the old reservation
    for ts in r.seats:
        ts.sold -= 1
    r.seats = []
    for x in range(0, rsize):
        r.seats.append(row.seats[x+new_idx])
        row.seats[x+new_idx].sold += 1
    # Place the new reservation
    return (h, reservations)
    
def E(s):
    (h, reservations) = s
    energy = 0
    for r in reservations:
        for seat in r.seats:
            energy -= seat.score
            if seat.sold > 1:
                energy += seat.sold * seat.score
    return energy

def P(e, en, t):
    if en < e:
        return 1
    else:
        return math.exp((e-en)/t)

def rand():
    return random.random()

def calc_emax(num_guests, h):
    seats = []
    for x in h.rows:
        for s in x.seats:
            seats.append(s)
    ss = sorted(seats)
    res = 0
    for x in range(0, num_guests):
        res += ss[x].score
    return res

def num_guests(reservations):
    res = 0
    for r in reservations:
        res += r.len
    return res
    
reservations = load_reservations(reservations_file)
h = load_hall(seats_file)

# make initial state with ff
s0 = firstfit(h, reservations)

s = s0; e = E(s)                         # Initial state, energy.
sb = deepcopy(s); eb = e                 # Initial "best" solution
k = 0                                    # Energy evaluation count.

kmax = 1600
#kmax = len(reservations) * 10
emax = 0-calc_emax(num_guests(reservations), h)

i = 0
while k < kmax and e > emax:                 # While time remains & not good enough:
    i+=1
    sn = neighbour(deepcopy(s))              #   Pick some neighbour.
    en = E(sn)                               #   Compute its energy.
    if en < eb:                              #   Is this a new best?
        sb = deepcopy(sn); eb = en           #     Yes, save it.
    if P(e, en, temp(k/kmax)) > rand():      #   Should we move to it?
        s = deepcopy(sn); e = en             #     Yes, change state.
    k = k + 1                                #   One more evaluation done
    log("""Status: en: %s, eb: %s, e: %s""" % (en, eb, e), HINT)
log(80*"=" + "\n" + str(sb), NOTE)           # Return the best solution found.

#log(h.pp(), NOTE)
log("----------- ", NOTE)
log("sb: ", NOTE)
(h, reservations) = sb
for r in reservations:
    log(r.pp(), NOTE)

log("Iterations: %s" % i, NOTE)
log(e, NOTE)
log(emax, NOTE)

hall_dr = show_hall.hall_drawer(h, reservations)
hall_dr.draw_hall()

New Paste


Do not write anything in this field if you're a human.

Go to most recent paste.