Exemplo n.º 1
0
 def __init__(self, seedInput = 0, IAT = 3, ST = 8, pi = None,
              server_num = 3, queueing_mode = 'shortest',
              graphics_mode = 'off'):
     '''
     Constructor of the class, sets initial values for class attributes
     Post: self.ii, self.seed, self.IAT, self.ST, self.currentTime,
     self.eventTable, self.waitingTime, self.TIS, self.serviceTime,
     self.eventCounter, self.customerCounter, self.server, self.sqList
     self.pi
     '''
     self.ii = 0
     seed(seedInput)
     self.seed = seedInput
     self.IAT = IAT
     self.ST = ST
     self.currentTime = 0.0
     self.eventTable = PriorityQueue()
     # waiting time of customers
     self.waitingTime = {}
     # time in system for each customer
     self.TIS = {}
     # service time for the corresponding customer
     self.serviceTime = {}
     self.eventCounter = 0
     self.customerCounter = 0
     self.set_mode(server_num, queueing_mode, graphics_mode)
     self.server = [IDLE for i in range(self.server_num)]
     self.sqList = [Queue() for i in range(self.queue_num)]
     # Equal probabilities by default
     if pi == None:
         pi = [1/float(self.queue_num) for i in range(self.queue_num)]
     #Ensure the probabilities sum to one
     pi[self.queue_num - 1] = 1 - sum(pi[:self.queue_num-1])
     self.pi = pi
     # Add first arrival event
     self.add_event(ARRIVE, self.currentTime)
Exemplo n.º 2
0
elif branch_strategy == FIXED:
    print "Fixed order"
else:
    print "Unknown branching strategy %s" %branch_strategy

if search_strategy == DEPTH_FIRST:
    print "Depth first search strategy"
elif search_strategy == BEST_FIRST:
    print "Best first search strategy"
else:
    print "Unknown search strategy %s" %search_strategy

print "==========================================="

# List of candidate nodes
Q = PriorityQueue()

# The current tree depth
cur_depth = 0
cur_index = 0

# Timer
timer = time.time()

Q.push((0, None, None, None, None), INFINITY)

# Branch and Bound Loop
while not Q.isEmpty():

    cur_index, parent, branch_var, sense, rhs = Q.pop()
    if cur_index is not 0:
Exemplo n.º 3
0
def BranchAndBoundCylp(T, CONSTRAINTS, VARIABLES, OBJ, MAT, RHS,
                   branch_strategy=MOST_FRACTIONAL,
                   search_strategy=DEPTH_FIRST,
                   complete_enumeration=False,
                   display_interval=None,
                   binary_vars=True):
    if T.get_layout() == 'dot2tex':
        cluster_attrs = {'name':'Key', 'label':r'\text{Key}', 'fontsize':'12'}
        T.add_node('C', label = r'\text{Candidate}', style = 'filled',
                      color = 'yellow', fillcolor = 'yellow')
        T.add_node('I', label = r'\text{Infeasible}', style = 'filled',
                      color = 'orange', fillcolor = 'orange')
        T.add_node('S', label = r'\text{Solution}', style = 'filled',
                      color = 'lightblue', fillcolor = 'lightblue')
        T.add_node('P', label = r'\text{Pruned}', style = 'filled',
                      color = 'red', fillcolor = 'red')
        T.add_node('PC', label = r'\text{Pruned}$\\ $\text{Candidate}', style = 'filled',
                      color = 'red', fillcolor = 'yellow')
    else:
        cluster_attrs = {'name':'Key', 'label':'Key', 'fontsize':'12'}
        T.add_node('C', label = 'Candidate', style = 'filled',
                      color = 'yellow', fillcolor = 'yellow')
        T.add_node('I', label = 'Infeasible', style = 'filled',
                      color = 'orange', fillcolor = 'orange')
        T.add_node('S', label = 'Solution', style = 'filled',
                      color = 'lightblue', fillcolor = 'lightblue')
        T.add_node('P', label = 'Pruned', style = 'filled',
                      color = 'red', fillcolor = 'red')
        T.add_node('PC', label = 'Pruned \n Candidate', style = 'filled',
                      color = 'red', fillcolor = 'yellow')
    T.add_edge('C', 'I', style = 'invisible', arrowhead = 'none')
    T.add_edge('I', 'S', style = 'invisible', arrowhead = 'none')
    T.add_edge('S', 'P', style = 'invisible', arrowhead = 'none')
    T.add_edge('P', 'PC', style = 'invisible', arrowhead = 'none')
    T.create_cluster(['C', 'I', 'S', 'P', 'PC'], cluster_attrs)

    # Change to CyLP format
    cyOBJ = CyLPArray([-val for val in OBJ.values()]) # CyLP takes min
    cyMAT = np.matrix([MAT[v] for v in VARIABLES]).T
    cyRHS = CyLPArray(RHS)


    # The initial lower bound
    LB = -INFINITY
    # The number of LP's solved, and the number of nodes solved
    node_count = 1
    iter_count = 0
    lp_count = 0

    numCons = len(CONSTRAINTS)
    numVars = len(VARIABLES)
    # List of incumbent solution variable values
    opt = dict([(i, 0) for i in VARIABLES])
    pseudo_u = dict((i, (OBJ[i], 0)) for i in VARIABLES)
    pseudo_d = dict((i, (OBJ[i], 0)) for i in VARIABLES)
    print("===========================================")
    print("Starting Branch and Bound")
    if branch_strategy == MOST_FRACTIONAL:
        print("Most fractional variable")
    elif branch_strategy == FIXED_BRANCHING:
        print("Fixed order")
    elif branch_strategy == PSEUDOCOST_BRANCHING:
        print("Pseudocost brancing")
    else:
        print("Unknown branching strategy %s" %branch_strategy)
    if search_strategy == DEPTH_FIRST:
        print("Depth first search strategy")
    elif search_strategy == BEST_FIRST:
        print("Best first search strategy")
    else:
        print("Unknown search strategy %s" %search_strategy)
    print("===========================================")
    # List of candidate nodes
    Q = PriorityQueue()
    # The current tree depth
    cur_depth = 0
    cur_index = 0
    # Timer
    timer = time.time()
    Q.push(0, -INFINITY, (0, None, None, None, None, None, None))
    # Branch and Bound Loop
    while not Q.isEmpty():
        infeasible = False
        integer_solution = False
        (cur_index, parent, relax, branch_var, branch_var_value, sense,
        rhs) = Q.pop()
        if cur_index is not 0:
            cur_depth = T.get_node_attr(parent, 'level') + 1
        else:
            cur_depth = 0
        print("")
        print("----------------------------------------------------")
        print("")
        if LB > -INFINITY:
            print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,LB))
        else:
            print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,"None"))
        if relax is not None and relax <= LB:
            print("Node pruned immediately by bound")
            T.set_node_attr(parent, 'color', 'red')
            continue
        #====================================
        #    LP Relaxation
        #====================================
        # Compute lower bound by LP relaxation
        prob = CyLPModel()

        # CyLP do not allow change variable object without model
        if binary_vars:
            var = prob.addVariable('x', dim=len(VARIABLES))
            prob += 0 <= var <= 1
        else:
            var = prob.addVariable('x', dim=len(VARIABLES))
            prob += 0 <= var # To avoid random generated problems be unbounded


        prob += cyMAT * var <= RHS
        prob.objective = cyOBJ * var
        s = CyClpSimplex(prob)

        # Fix all prescribed variables
        branch_vars = []
        if cur_index is not 0:
            sys.stdout.write("Branching variables: ")
            branch_vars.append(branch_var)
            if sense == '>=':
                prob += var[int(branch_var[1:])] >= rhs # slice the name for index
            else:
                prob += var[int(branch_var[1:])] <= rhs # slice the name for index
            print(branch_var, end=' ')
            pred = parent
            while not str(pred) == '0':
                pred_branch_var = T.get_node_attr(pred, 'branch_var')
                pred_rhs = T.get_node_attr(pred, 'rhs')
                pred_sense = T.get_node_attr(pred, 'sense')
                if pred_sense == '<=':
                    prob += var[int(pred_branch_var[1:])] <= pred_rhs
                else:
                    prob += var[int(pred_branch_var[1:])] >= pred_rhs
                print(pred_branch_var, end=' ')
                branch_vars.append(pred_branch_var)
                pred = T.get_node_attr(pred, 'parent')
            print()
        # Solve the LP relaxation
        s = CyClpSimplex(prob)
        s.initialSolve()
        lp_count = lp_count +1

        if (s.getStatusCode() < 0):
            print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')
            print(lp_count)
            print(s.getStatusCode())
            print(s.primal())
            print(s.objectiveValue)
            print(s.primalVariableSolution)
            print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')

        # Check infeasibility
        #-1 - unknown e.g. before solve or if postSolve says not optimal
        #0 - optimal
        #1 - primal infeasible
        #2 - dual infeasible
        #3 - stopped on iterations or time
        #4 - stopped due to errors
        #5 - stopped by event handler (virtual int ClpEventHandler::event())
        infeasible = (s.getStatusCode() in [-1,1,3,4,5])
        # Print status
        if infeasible:
            print("LP Solved, status: Infeasible")
        else:
            print("LP Solved, status: %s, obj: %s" %(s.getStatusString(),-s.objectiveValue))

        if(s.getStatusCode() == 0):
            relax = -s.objectiveValue
            # Update pseudocost
            if branch_var != None:
                if sense == '<=':
                    pseudo_d[branch_var] = (
                    old_div((pseudo_d[branch_var][0]*pseudo_d[branch_var][1] +
                    old_div((T.get_node_attr(parent, 'obj') - relax),
                    (branch_var_value - rhs))),(pseudo_d[branch_var][1]+1)),
                    pseudo_d[branch_var][1]+1)
                else:
                    pseudo_u[branch_var] = (
                    old_div((pseudo_u[branch_var][0]*pseudo_d[branch_var][1] +
                     old_div((T.get_node_attr(parent, 'obj') - relax),
                     (rhs - branch_var_value))),(pseudo_u[branch_var][1]+1)),
                    pseudo_u[branch_var][1]+1)
            var_values = dict([(i, s.primalVariableSolution['x'][int(i[1:])]) for i in VARIABLES])
            integer_solution = 1
            for i in VARIABLES:
                if (abs(round(var_values[i]) - var_values[i]) > .001):
                    integer_solution = 0
                    break
            # Determine integer_infeasibility_count and
            # Integer_infeasibility_sum for scatterplot and such
            integer_infeasibility_count = 0
            integer_infeasibility_sum = 0.0
            for i in VARIABLES:
                if (var_values[i] not in set([0,1])):
                    integer_infeasibility_count += 1
                    integer_infeasibility_sum += min([var_values[i],
                                                      1.0-var_values[i]])
            if (integer_solution and relax>LB):
                LB = relax
                for i in VARIABLES:
                    # These two have different data structures first one
                    #list, second one dictionary
                    opt[i] = var_values[i]
                print("New best solution found, objective: %s" %relax)
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            elif (integer_solution and relax<=LB):
                print("New integer solution found, objective: %s" %relax)
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            else:
                print("Fractional solution:")
                for i in VARIABLES:
                    if var_values[i] > 0:
                        print("%s = %s" %(i, var_values[i]))
            #For complete enumeration
            if complete_enumeration:
                relax = LB - 1
        else:
            relax = INFINITY
        if integer_solution:
            print("Integer solution")
            BBstatus = 'S'
            status = 'integer'
            color = 'lightblue'
        elif infeasible:
            print("Infeasible node")
            BBstatus = 'I'
            status = 'infeasible'
            color = 'orange'
        elif not complete_enumeration and relax <= LB:
            print("Node pruned by bound (obj: %s, UB: %s)" %(relax,LB))
            BBstatus = 'P'
            status = 'fathomed'
            color = 'red'
        elif cur_depth >= numVars :
            print("Reached a leaf")
            BBstatus = 'fathomed'
            status = 'L'
        else:
            BBstatus = 'C'
            status = 'candidate'
            color = 'yellow'
        if BBstatus is 'I':
            if T.get_layout() == 'dot2tex':
                label = '\text{I}'
            else:
                label = 'I'
        else:
            label = "%.1f"%relax
        if iter_count == 0:
            if status is not 'candidate':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            if status is 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before '+\
                        'first incumbent.')
            T.AddOrUpdateNode(0, None, None, 'candidate', relax,
                             integer_infeasibility_count,
                             integer_infeasibility_sum,
                             label = label,
                             obj = relax, color = color,
                             style = 'filled', fillcolor = color)
            if status is 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = -1
                T._new_integer_solution = True
    #           #Currently broken
    #           if ETREE_INSTALLED and T.attr['display'] == 'svg':
    #               T.write_as_svg(filename = "node%d" % iter_count,
    #                                 nextfile = "node%d" % (iter_count + 1),
    #                                 highlight = cur_index)
        else:
            _direction = {'<=':'L', '>=':'R'}
            if status is 'infeasible':
                integer_infeasibility_count = T.get_node_attr(parent,
                                     'integer_infeasibility_count')
                integer_infeasibility_sum = T.get_node_attr(parent,
                                     'integer_infeasibility_sum')
                relax = T.get_node_attr(parent, 'lp_bound')
            elif status is 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before'+\
                        ' first incumbent.')
                    print('  This may indicate an error in the input file.')
            elif status is 'integer':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            T.AddOrUpdateNode(cur_index, parent, _direction[sense],\
                                 status, relax,\
                                 integer_infeasibility_count,\
                                 integer_infeasibility_sum,\
                                 branch_var = branch_var,\
                                 branch_var_value = var_values[branch_var],\
                                 sense = sense, rhs = rhs, obj = relax,\
                                 color = color, style = 'filled',\
                                 label = label, fillcolor = color)
            if status is 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = parent
                T._new_integer_solution = True
            # Currently Broken
    #           if ETREE_INSTALLED and T.attr['display'] == 'svg':
    #               T.write_as_svg(filename = "node%d" % iter_count,
    #                                 prevfile = "node%d" % (iter_count - 1),
    #                                 nextfile = "node%d" % (iter_count + 1),
    #                                 highlight = cur_index)
            if T.get_layout() == 'dot2tex':
                _dot2tex_label = {'>=':' \geq ', '<=':' \leq '}
                T.set_edge_attr(parent, cur_index, 'label',\
                                   str(branch_var) + _dot2tex_label[sense] +\
                                   str(rhs))
            else:
                T.set_edge_attr(parent, cur_index, 'label',\
                                   str(branch_var) + sense + str(rhs))
        iter_count += 1
        if BBstatus == 'C':
            # Branching:
            # Choose a variable for branching
            branching_var = None
            if branch_strategy == FIXED_BRANCHING:
                #fixed order
                for i in VARIABLES:
                    frac = min(s.primalVariableSolution['x'][int(i[1:])]-math.floor(s.primalVariableSolution['x'][int(i[1:])]),\
                               math.ceil(s.primalVariableSolution['x'][int(i[1:])]) - s.primalVariableSolution['x'][int(i[1:])])
                    if (frac > 0):
                        min_frac = frac
                        branching_var = i
                        # TODO(aykut): understand this break
                        break
            elif branch_strategy == MOST_FRACTIONAL:
                #most fractional variable
                min_frac = -1
                for i in VARIABLES:
                    frac = min(s.primalVariableSolution['x'][int(i[1:])]-math.floor(s.primalVariableSolution['x'][int(i[1:])]),\
                               math.ceil(s.primalVariableSolution['x'][int(i[1:])])- s.primalVariableSolution['x'][int(i[1:])])
                    if (frac> min_frac):
                        min_frac = frac
                        branching_var = i
            elif branch_strategy == PSEUDOCOST_BRANCHING:
                scores = {}
                for i in VARIABLES:
                    # find the fractional solutions
                    if (s.primalVariableSolution['x'][int(i[1:])] - math.floor(s.primalVariableSolution['x'][int(i[1:])])) != 0:
                        scores[i] = min(pseudo_u[i][0]*(1-s.primalVariableSolution['x'][int(i[1:])]),\
                                        pseudo_d[i][0]*s.primalVariableSolution['x'][int(i[1:])])
                    # sort the dictionary by value
                branching_var = sorted(list(scores.items()),
                                       key=lambda x : x[1])[-1][0]
            else:
                print("Unknown branching strategy %s" %branch_strategy)
                exit()
            if branching_var is not None:
                print("Branching on variable %s" %branching_var)
            #Create new nodes
            if search_strategy == DEPTH_FIRST:
                priority = (-cur_depth - 1, -cur_depth - 1)
            elif search_strategy == BEST_FIRST:
                priority = (-relax, -relax)
            elif search_strategy == BEST_ESTIMATE:
                priority = (-relax - pseudo_d[branching_var][0]*\
                                 (math.floor(s.primalVariableSolution['x'][int(branching_var[1:])]) -\
                                      s.primalVariableSolution['x'][int(branching_var[1:])]),\
                            -relax + pseudo_u[branching_var][0]*\
                                 (math.ceil(s.primalVariableSolution['x'][int(branching_var[1:])]) -\
                                      s.primalVariableSolution['x'][int(branching_var[1:])]))
            node_count += 1
            Q.push(node_count, priority[0], (node_count, cur_index, relax, branching_var,
                    var_values[branching_var],
                    '<=', math.floor(s.primalVariableSolution['x'][int(branching_var[1:])])))
            node_count += 1
            Q.push(node_count, priority[1], (node_count, cur_index, relax, branching_var,
                    var_values[branching_var],
                    '>=', math.ceil(s.primalVariableSolution['x'][int(branching_var[1:])])))
            T.set_node_attr(cur_index, color, 'green')
        if T.root is not None and display_interval is not None and\
                iter_count%display_interval == 0:
            T.display(count=iter_count)

    timer = int(math.ceil((time.time()-timer)*1000))
    print("")
    print("===========================================")
    print("Branch and bound completed in %sms" %timer)
    print("Strategy: %s" %branch_strategy)
    if complete_enumeration:
        print("Complete enumeration")
    print("%s nodes visited " %node_count)
    print("%s LP's solved" %lp_count)
    print("===========================================")
    print("Optimal solution")
    #print optimal solution
    for i in sorted(VARIABLES):
        if opt[i] > 0:
            print("%s = %s" %(i, opt[i]))
    print("Objective function value")
    print(LB)
    print("===========================================")
    if T.attr['display'] is not 'off':
        T.display(count=iter_count)
    T._lp_count = lp_count
    return LB,opt
Exemplo n.º 4
0
elif branch_strategy == FIXED:
    print("Fixed order")
else:
    print("Unknown branching strategy %s" % branch_strategy)

if search_strategy == DEPTH_FIRST:
    print("Depth first search strategy")
elif search_strategy == BEST_FIRST:
    print("Best first search strategy")
else:
    print("Unknown search strategy %s" % search_strategy)

print("===========================================")

# List of candidate nodes
Q = PriorityQueue()

# The current tree depth
cur_depth = 0
cur_index = 0

# Timer
timer = time.time()

Q.push((0, None, None, None, None), INFINITY)

# Branch and Bound Loop
while not Q.isEmpty():

    cur_index, parent, branch_var, sense, rhs = Q.pop()
    if cur_index is not 0:
Exemplo n.º 5
0
def BranchAndBound(T, CONSTRAINTS, VARIABLES, OBJ, MAT, RHS,
                   branch_strategy=MOST_FRACTIONAL,
                   search_strategy=DEPTH_FIRST,
                   complete_enumeration=False,
                   display_interval=None,
                   binary_vars=True,
                   solver='dynamic',
                   rel_param=(4, 3, 1 / 6, 5),
                   more_return=False
                   ):
    """
        solver: 
            dynamic       - initialSolve
            primalSimplex - initialPrimalSolve 
            dualSimplex   - initialDualSolve

        Parameter Tuple for Reliability Branching
        rel_param = (eta_rel,gamma,mu,lambda):
            eta_rel = 0       - psesudocost branching
            eta_rel = 1       - psesudocost branching with strong branching initialization
            eta_rel = 4,8     - best performing reliability branching rules
            eta_rel = inifity - strong branching
            gamma             - max number of simplex iterations in score calculation
            mu                - score factor, a number between 0 and 1. Paper uses 1/6
            lambda            - if max score is not updated for lambda 
                                consecutive iterations, stop.
        more_return:
            False - return maximizer and max 
            True  - also return a dict of stats(time, tree size, LP solved)
    """
    ACTUAL_BRANCH_STRATEGY = branch_strategy
    # reliability branching parameters
    eta_rel, gamma, mu, lam = rel_param
    # hybrid branching parameters
    total_num_pivot = average_num_pivot = 0
    # translate problems into cylp format
    cyOBJ = CyLPArray([-val for val in OBJ.values()])
    cyMAT = np.matrix([MAT[v] for v in VARIABLES]).T
    cyRHS = CyLPArray(RHS)
    OBJ = cyOBJ
    MAT = cyMAT
    RHS = cyRHS
    if T.get_layout() == 'dot2tex':
        cluster_attrs = {'name': 'Key', 'label': r'\text{Key}', 'fontsize': '12'}
        T.add_node('C', label=r'\text{Candidate}', style='filled',
                   color='yellow', fillcolor='yellow')
        T.add_node('I', label=r'\text{Infeasible}', style='filled',
                   color='orange', fillcolor='orange')
        T.add_node('S', label=r'\text{Solution}', style='filled',
                   color='lightblue', fillcolor='lightblue')
        T.add_node('P', label=r'\text{Pruned}', style='filled',
                   color='red', fillcolor='red')
        T.add_node('PC', label=r'\text{Pruned}$\\ $\text{Candidate}', style='filled',
                   color='red', fillcolor='yellow')
    else:
        cluster_attrs = {'name': 'Key', 'label': 'Key', 'fontsize': '12'}
        T.add_node('C', label='Candidate', style='filled',
                   color='yellow', fillcolor='yellow')
        T.add_node('I', label='Infeasible', style='filled',
                   color='orange', fillcolor='orange')
        T.add_node('S', label='Solution', style='filled',
                   color='lightblue', fillcolor='lightblue')
        T.add_node('P', label='Pruned', style='filled',
                   color='red', fillcolor='red')
        T.add_node('PC', label='Pruned \n Candidate', style='filled',
                   color='red', fillcolor='yellow')
    T.add_edge('C', 'I', style='invisible', arrowhead='none')
    T.add_edge('I', 'S', style='invisible', arrowhead='none')
    T.add_edge('S', 'P', style='invisible', arrowhead='none')
    T.add_edge('P', 'PC', style='invisible', arrowhead='none')
    T.create_cluster(['C', 'I', 'S', 'P', 'PC'], cluster_attrs)
    # The initial lower bound
    LB = -INFINITY
    # The number of LP's solved, and the number of nodes solved
    node_count = 1
    iter_count = 0
    lp_count = 0  # The problems that are fully solved during
    # Reliability and Hybrid branching is also couned here
    # For reliability branching
    half_solved = 0  # record number problems been halfly solved when calculate scores
    full_solved = 0  # record number problems been fully solved when calculate scores

    numVars = len(VARIABLES)
    # List of incumbent solution variable values
    opt = dict([(i, 0) for i in range(len(VARIABLES))])
    pseudo_u = dict((i, (-OBJ[i], 0)) for i in range(len(VARIABLES)))
    pseudo_d = dict((i, (-OBJ[i], 0)) for i in range(len(VARIABLES)))

    print("===========================================")
    print("Starting Branch and Bound")
    if branch_strategy == MOST_FRACTIONAL:
        print("Most fractional variable")
    elif branch_strategy == FIXED_BRANCHING:
        print("Fixed order")
    elif branch_strategy == PSEUDOCOST_BRANCHING:
        print("Pseudocost brancing")
    elif branch_strategy == RELIABILITY_BRANCHING:
        print("Reliability branching")
    elif branch_strategy == HYBRID:
        print('Hybrid strong/pseduocost branching')
    else:
        print("Unknown branching strategy %s" % branch_strategy)
    if search_strategy == DEPTH_FIRST:
        print("Depth first search strategy")
    elif search_strategy == BEST_FIRST:
        print("Best first search strategy")
    elif search_strategy == BEST_ESTIMATE:
        print("Best estimate search strategy")
    else:
        print("Unknown search strategy %s" % search_strategy)
    print("===========================================")
    # List of candidate nodes
    Q = PriorityQueue()
    # The current tree depth
    cur_depth = 0
    cur_index = 0
    # Timer
    timer = time.time()
    Q.push(0, -INFINITY, (0, None, None, None, None, None, None))
    # Branch and Bound Loop
    while not Q.isEmpty():
        # maximum allowed strong branch performed
        if branch_strategy == HYBRID and cur_depth > max(int(len(VARIABLES) * 0.2), 5):
            branch_strategy = PSEUDOCOST_BRANCHING
            print("Switch from strong branch to psedocost branch")
        infeasible = False
        integer_solution = False
        (cur_index, parent, relax, branch_var, branch_var_value, sense,
         rhs) = Q.pop()
        if cur_index is not 0:
            cur_depth = T.get_node_attr(parent, 'level') + 1
        else:
            cur_depth = 0
        print("")
        print("----------------------------------------------------")
        print("")
        if LB > -INFINITY:
            print("Node: %s, Depth: %s, LB: %s" % (cur_index, cur_depth, LB))
        else:
            print("Node: %s, Depth: %s, LB: %s" % (cur_index, cur_depth, "None"))
        if relax is not None and relax <= LB:
            print("Node pruned immediately by bound")
            T.set_node_attr(parent, 'color', 'red')
            continue
        # ====================================
        #    LP Relaxation
        # ====================================
        # Compute lower bound by LP relaxation
        prob = CyLPModel()
        if binary_vars:
            x = prob.addVariable('x', dim=len(VARIABLES))
            prob += 0 <= x <= 1
        else:
            x = prob.addVariable('x', dim=len(VARIABLES))
        prob.objective = OBJ * x
        prob += MAT * x <= RHS
        # Fix all prescribed variables
        branch_vars = []
        if cur_index is not 0:
            sys.stdout.write("Branching variables: ")
            branch_vars.append(branch_var)
            if sense == '>=':
                prob += x[branch_var] >= rhs
            else:
                prob += x[branch_var] <= rhs
            print('x_{}'.format(branch_var), end=' ')
            pred = parent
            while not str(pred) == '0':
                pred_branch_var = T.get_node_attr(pred, 'branch_var')
                pred_rhs = T.get_node_attr(pred, 'rhs')
                pred_sense = T.get_node_attr(pred, 'sense')
                if pred_sense == '<=':
                    prob += x[pred_branch_var] <= pred_rhs
                else:
                    prob += x[pred_branch_var] >= pred_rhs
                print(pred_branch_var, end=' ')
                branch_vars.append(pred_branch_var)
                pred = T.get_node_attr(pred, 'parent')
            print()
        # Solve the LP relaxation
        s = CyClpSimplex(prob)
        if solver == 'primalSimplex':
            s.initialPrimalSolve()
        elif solver == 'dualSimplex':
            s.initialDualSolve()
        else:
            s.initialSolve()
        lp_count = lp_count + 1
        total_num_pivot += s.iteration
        average_num_pivot = total_num_pivot / lp_count
        # Check infeasibility
        # -1 - unknown e.g. before solve or if postSolve says not optimal
        # 0 - optimal
        # 1 - primal infeasible
        # 2 - dual infeasible
        # 3 - stopped on iterations or time
        # 4 - stopped due to errors
        # 5 - stopped by event handler (virtual int ClpEventHandler::event())
        infeasible = (s.getStatusCode() in [1, 2])
        # Print status
        if infeasible:
            print("LP Solved, status: Infeasible")
        else:
            print("LP Solved, status: %s, obj: %s" % (s.getStatusString(),
                                                      s.objectiveValue))
        if(s.getStatusCode() == 0):
            relax = -round(s.objectiveValue,7)
            # Update pseudocost
            if branch_var != None:
                if sense == '<=':
                    pseudo_d[branch_var] = (
                        old_div((pseudo_d[branch_var][0] * pseudo_d[branch_var][1] +
                                 old_div((T.get_node_attr(parent, 'obj') - relax),
                                         (branch_var_value - rhs))),
                                (pseudo_d[branch_var][1] + 1)),
                        pseudo_d[branch_var][1] + 1)
                else:
                    pseudo_u[branch_var] = (
                        old_div((pseudo_u[branch_var][0] * pseudo_d[branch_var][1] +
                                 old_div((T.get_node_attr(parent, 'obj') - relax),
                                         (rhs - branch_var_value))),
                                (pseudo_u[branch_var][1] + 1)),
                        pseudo_u[branch_var][1] + 1)
            var_values = dict([(i, round(s.primalVariableSolution['x'][i],7))
                               for i in range(len(VARIABLES))])
            integer_solution = 1
            for i in range(len(VARIABLES)):
                if (abs(round(var_values[i]) - var_values[i]) > .001):
                    integer_solution = 0
                    break
            # Determine integer_infeasibility_count and
            # Integer_infeasibility_sum for scatterplot and such
            integer_infeasibility_count = 0
            integer_infeasibility_sum = 0.0
            for i in range(len(VARIABLES)):
                if (var_values[i] not in set([0, 1])):
                    integer_infeasibility_count += 1
                    integer_infeasibility_sum += min([var_values[i],
                                                      1.0 - var_values[i]])
            if (integer_solution and relax > LB):
                LB = relax
                for i in range(len(VARIABLES)):
                    # These two have different data structures first one
                    # list, second one dictionary
                    opt[i] = var_values[i]
                print("New best solution found, objective: %s" % relax)
                for i in range(len(VARIABLES)):
                    if var_values[i] > 0:
                        print("%s = %s" % (i, var_values[i]))
            elif (integer_solution and relax <= LB):
                print("New integer solution found, objective: %s" % relax)
                for i in range(len(VARIABLES)):
                    if var_values[i] > 0:
                        print("%s = %s" % (i, var_values[i]))
            else:
                print("Fractional solution:")
                for i in range(len(VARIABLES)):
                    if var_values[i] > 0:
                        print("x%s = %s" % (i, var_values[i]))
            # For complete enumeration
            if complete_enumeration:
                relax = LB - 1
        else:
            relax = INFINITY
        if integer_solution:
            print("Integer solution")
            BBstatus = 'S'
            status = 'integer'
            color = 'lightblue'
        elif infeasible:
            print("Infeasible node")
            BBstatus = 'I'
            status = 'infeasible'
            color = 'orange'
        elif not complete_enumeration and relax <= LB:
            print("Node pruned by bound (obj: %s, UB: %s)" % (relax, LB))
            BBstatus = 'P'
            status = 'fathomed'
            color = 'red'
        elif cur_depth >= numVars:
            print("Reached a leaf")
            BBstatus = 'fathomed'
            status = 'L'
        else:
            BBstatus = 'C'
            status = 'candidate'
            color = 'yellow'
        if BBstatus is 'I':
            if T.get_layout() == 'dot2tex':
                label = '\text{I}'
            else:
                label = 'I'
        else:
            label = "%.1f" % relax
        if iter_count == 0:
            if status is not 'candidate':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            if status is 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before ' +
                          'first incumbent.')
            T.AddOrUpdateNode(0, None, None, 'candidate', relax,
                              integer_infeasibility_count,
                              integer_infeasibility_sum,
                              label=label,
                              obj=relax, color=color,
                              style='filled', fillcolor=color)
            if status is 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = -1
                T._new_integer_solution = True
    #           #Currently broken
    #           if ETREE_INSTALLED and T.attr['display'] == 'svg':
    #               T.write_as_svg(filename = "node%d" % iter_count,
    #                                 nextfile = "node%d" % (iter_count + 1),
    #                                 highlight = cur_index)
        else:
            _direction = {'<=': 'L', '>=': 'R'}
            if status is 'infeasible':
                integer_infeasibility_count = T.get_node_attr(parent,
                                                              'integer_infeasibility_count')
                integer_infeasibility_sum = T.get_node_attr(parent,
                                                            'integer_infeasibility_sum')
                relax = T.get_node_attr(parent, 'lp_bound')
            elif status is 'fathomed':
                if T._incumbent_value is None:
                    print('WARNING: Encountered "fathom" line before' +
                          ' first incumbent.')
                    print('  This may indicate an error in the input file.')
            elif status is 'integer':
                integer_infeasibility_count = None
                integer_infeasibility_sum = None
            T.AddOrUpdateNode(cur_index, parent, _direction[sense],
                              status, relax,
                              integer_infeasibility_count,
                              integer_infeasibility_sum,
                              branch_var=branch_var,
                              branch_var_value=var_values[branch_var],
                              sense=sense, rhs=rhs, obj=relax,
                              color=color, style='filled',
                              label=label, fillcolor=color)
            if status is 'integer':
                T._previous_incumbent_value = T._incumbent_value
                T._incumbent_value = relax
                T._incumbent_parent = parent
                T._new_integer_solution = True
            # Currently Broken
    #           if ETREE_INSTALLED and T.attr['display'] == 'svg':
    #               T.write_as_svg(filename = "node%d" % iter_count,
    #                                 prevfile = "node%d" % (iter_count - 1),
    #                                 nextfile = "node%d" % (iter_count + 1),
    #                                 highlight = cur_index)
            if T.get_layout() == 'dot2tex':
                _dot2tex_label = {'>=': ' \geq ', '<=': ' \leq '}
                T.set_edge_attr(parent, cur_index, 'label',
                                str(branch_var) + _dot2tex_label[sense] +
                                str(rhs))
            else:
                T.set_edge_attr(parent, cur_index, 'label',
                                str(branch_var) + sense + str(rhs))
        iter_count += 1
        if BBstatus == 'C':
            # Branching:
            # Choose a variable for branching
            branching_var = None
            if branch_strategy == FIXED_BRANCHING:
                # fixed order
                for i in range(len(VARIABLES)):
                    frac = min(var_values[i] - math.floor(var_values[i]),
                               math.ceil(var_values[i]) - var_values[i])
                    if (frac > 0):
                        min_frac = frac
                        branching_var = i
                        # TODO(aykut): understand this break
                        break
            elif branch_strategy == MOST_FRACTIONAL:
                # most fractional variable
                min_frac = -1
                for i in range(len(VARIABLES)):
                    frac = min(var_values[i] - math.floor(var_values[i]),
                               math.ceil(var_values[i]) - var_values[i])
                    if (frac > min_frac):
                        min_frac = frac
                        branching_var = i
            elif branch_strategy == PSEUDOCOST_BRANCHING:
                scores = {}
                for i in range(len(VARIABLES)):
                    # find the fractional solutions
                    if abs(var_values[i] - math.floor(var_values[i])) > 1e-8:
                        scores[i] = min(pseudo_u[i][0] * (math.ceil(var_values[i])
                                                          - var_values[i]),
                                        pseudo_d[i][0] * (var_values[i]
                                                          - math.floor(var_values[i])))
                # sort the dictionary by value
                branching_var = sorted(list(scores.items()), key=lambda x: x[1])[-1][0]

            elif branch_strategy == RELIABILITY_BRANCHING:
                # Calculating Scores
                # The algorithm in paper is different from the one in Grumpy
                # I will try to use paper notations
                scores = {}
                for i in range(len(VARIABLES)):
                    # find the fractional solutions
                    if abs(var_values[i] - math.floor(var_values[i])) > 1e-8:
                        qp = pseudo_u[i][0] * (math.ceil(var_values[i])
                                               - var_values[i])  # q^+
                        qm = pseudo_d[i][0] * (var_values[i]
                                               - math.floor(var_values[i]))  # q^^-
                        scores[i] = (1 - mu) * min(qm, qp) + mu * max(qm, qp)

                # sort the dictionary by value
                candidate_vars = [en[0] for en in sorted(list(scores.items()), key=lambda x: x[1], reverse=True)]

                no_change = 0  # number of iterations that maximum of scores is not changed
                smax = scores[candidate_vars[0]]  # current maximum of scores
                for i in candidate_vars:
                    if min(pseudo_d[i][1], pseudo_u[i][1]) < eta_rel:
                        qp = pseudo_u[i][0] * (math.ceil(var_values[i]) - var_values[i])  # q^+
                        qm = pseudo_d[i][0] * (var_values[i] - math.floor(var_values[i]))  # q^^-

                        # left subproblem/down direction
                        s_left = CyClpSimplex(prob)
                        s_left += x[i] <= math.floor(var_values[i])
                        s_left.maxNumIteration = gamma  # solve for fixed number of iterations
                        s_left.dual()
                        if s_left.getStatusCode() == 0:
                            qm = relax + s_left.objectiveValue  # use a more reliable source to update q^-
                            full_solved = full_solved + 1
                            lp_count = lp_count + 1  # If the LP is fully solved, counter plus one
                        elif s_left.getStatusCode() == 3:
                            qm = relax + s_left.objectiveValue  # use a more reliable source to update q^-
                            half_solved = half_solved + 1

                        # right subproblem/up direction
                        s_right = CyClpSimplex(prob)
                        s_right += x[i] >= math.ceil(var_values[i])
                        s_right.maxNumIteration = gamma  # solve for fixed number of iterations
                        s_right.dual()
                        if s_right.getStatusCode() == 0:
                            qp = relax + s_right.objectiveValue   # use a more reliable source to update q^+
                            full_solved = full_solved + 1
                            lp_count = lp_count + 1  # If the LP is fully solved, counter plus one
                        elif s_right.getStatusCode() == 3:
                            qp = relax + s_right.objectiveValue  # use a more reliable source to update q^+
                            half_solved = half_solved + 1

                        scores[i] = (1 - mu) * min(qm, qp) + mu * max(qm, qp)
                        if (smax == scores[i]):
                            no_change += 1
                        elif (smax <= scores[i]):
                            no_change = 0
                            smax = scores[i]
                        else:
                            no_change = 0

                    if no_change >= lam:
                        break
                branching_var = sorted(list(scores.items()), key=lambda x: x[1])[-1][0]

            elif branch_strategy == HYBRID:
                scores = {}
                for i in range(len(VARIABLES)):
                    # find the fractional solutions
                    if abs(var_values[i] - math.floor(var_values[i])) > 1e-8:
                        scores[i] = min(pseudo_u[i][0] * (math.ceil(var_values[i])
                                                          - var_values[i]),
                                        pseudo_d[i][0] * (var_values[i]
                                                          - math.floor(var_values[i])))
                candidate_vars = [en[0] for en in sorted(list(scores.items()), key=lambda x: x[1], reverse=True)]
                restricted_candidate_vars = candidate_vars[:max(1, int(0.5 * len(candidate_vars)))]
                # print("Subset of candidate variables:")
                # print(restricted_candidate_vars)
                best_progress = 0
                branch_candidate = None
                for i in restricted_candidate_vars:
                    s = CyClpSimplex(prob)
                    s += math.floor(var_values[i]) <= x[i] <= math.ceil(var_values[i])
                    s.maxNumIteration = average_num_pivot * 2
                    s.dual()
                    if s.getStatusCode() == 0:
                        lp_count += 1
                    progress = relax - (-s.objectiveValue)
                    if (progress - best_progress) > 1e-8:
                        branch_candidate = i
                        best_progress = progress
                if branch_candidate is None:
                    branch_candidate = restricted_candidate_vars[0]
                branching_var = branch_candidate

            else:
                print("Unknown branching strategy %s" % branch_strategy)
                exit()
            if branching_var is not None:
                print("Branching on variable %s" % branching_var)
            # Create new nodes
            if search_strategy == DEPTH_FIRST:
                priority = (-cur_depth - 1, -cur_depth - 1)
            elif search_strategy == BEST_FIRST:
                priority = (-relax, -relax)
            elif search_strategy == BEST_ESTIMATE:
                priority = (-relax - pseudo_d[branching_var][0] *
                            (math.floor(var_values[branching_var]) - var_values[branching_var]),
                            -relax + pseudo_u[branching_var][0] *
                            (math.ceil(var_values[branching_var]) - var_values[branching_var]))
            node_count += 1
            Q.push(node_count, priority[0], (node_count, cur_index, relax, branching_var,
                                             var_values[branching_var],
                                             '<=', math.floor(var_values[branching_var])))
            node_count += 1
            Q.push(node_count, priority[1], (node_count, cur_index, relax, branching_var,
                                             var_values[branching_var],
                                             '>=', math.ceil(var_values[branching_var])))
            T.set_node_attr(cur_index, color, 'green')
        if T.root is not None and display_interval is not None and\
                iter_count % display_interval == 0:
            T.display(count=iter_count)

    timer = int(math.ceil((time.time() - timer) * 1000))
    print("")
    print("===========================================")
    print("Branch and bound completed in %sms" % timer)
    print("Strategy: %s" % ACTUAL_BRANCH_STRATEGY)
    if complete_enumeration:
        print("Complete enumeration")
    print("%s nodes visited " % node_count)
    print("%s LP's solved" % lp_count)
    print("===========================================")
    print("Optimal solution")
    # print optimal solution
    for i in range(len(VARIABLES)):
        if opt[i] > 0:
            print("x%s = %s" % (i, opt[i]))
    print("Objective function value")
    print(LB)
    print("===========================================")
    if T.attr['display'] is not 'off':
        T.display(count=iter_count)
    T._lp_count = lp_count

    if more_return:
        stat = {'Time': timer, 'Size': node_count, 'LP Solved': lp_count}
        if branch_strategy == RELIABILITY_BRANCHING:
            stat['LP Solved for Bounds'] = lp_count - full_solved
            stat['Halfly Solved'] = half_solved
            stat['Fully Solved'] = full_solved
        return opt, LB, stat
    
    return opt, LB
Exemplo n.º 6
0
class EventQueue(object):
    '''
    This class holds the attributes and methods for the simulation of M/M/s
    queueing system
    '''
    def __init__(self, seedInput = 0, IAT = 3, ST = 8, pi = None,
                 server_num = 3, queueing_mode = 'shortest',
                 graphics_mode = 'off'):
        '''
        Constructor of the class, sets initial values for class attributes
        Post: self.ii, self.seed, self.IAT, self.ST, self.currentTime,
        self.eventTable, self.waitingTime, self.TIS, self.serviceTime,
        self.eventCounter, self.customerCounter, self.server, self.sqList
        self.pi
        '''
        self.ii = 0
        seed(seedInput)
        self.seed = seedInput
        self.IAT = IAT
        self.ST = ST
        self.currentTime = 0.0
        self.eventTable = PriorityQueue()
        # waiting time of customers
        self.waitingTime = {}
        # time in system for each customer
        self.TIS = {}
        # service time for the corresponding customer
        self.serviceTime = {}
        self.eventCounter = 0
        self.customerCounter = 0
        self.set_mode(server_num, queueing_mode, graphics_mode)
        self.server = [IDLE for i in range(self.server_num)]
        self.sqList = [Queue() for i in range(self.queue_num)]
        # Equal probabilities by default
        if pi == None:
            pi = [1/float(self.queue_num) for i in range(self.queue_num)]
        #Ensure the probabilities sum to one
        pi[self.queue_num - 1] = 1 - sum(pi[:self.queue_num-1])
        self.pi = pi
        # Add first arrival event
        self.add_event(ARRIVE, self.currentTime)

    def set_mode(self, server_num = None, queueing_mode = None,
                 graphics_mode = None):
        '''
        server_num is a positive integer queueing_mode is either 'single',
        'random', or 'shortest' graphics_mode is either string 'off' or 'on'
        '''
        if queueing_mode:
            self.queueing_mode = queueing_mode
        if server_num:
            self.server_num = server_num
            if self.queueing_mode != 'single':
                self.queue_num = self.server_num
            else:
                self.queue_num = 1
        if graphics_mode:
            self.graphics_mode = graphics_mode
        if graphics_mode == 'on' and self.server_num > 50:
            print 'Only visualizing first 50 servers'

    def process_event(self, event):
        '''
        processes event given and updates sqList and eventTable accordingly
        '''
        if event.eventType == ARRIVE: 
            whichQueue, whichServer = self.which_queue()
            serviceTime = expovariate(1.0/self.ST)
            if whichServer == None:
                self.sqList[whichQueue].enqueue(Customer(self.currentTime, 
                                                         serviceTime, 
                                                         self.customerCounter))
            else:
                self.waitingTime[self.customerCounter] = 0
                self.serviceTime[self.customerCounter] = serviceTime
                self.add_event(DEPART, self.currentTime + serviceTime, 
                               whichServer)
            self.customerCounter += 1
            self.add_event(ARRIVE, self.currentTime+expovariate(1.0/self.IAT))
        elif event.eventType == DEPART:
            if self.queue_num == 1:
                q = self.sqList[0]
            else:
                q = self.sqList[event.serverNumber]
            if not q.isEmpty():
                customer = q.dequeue()
                self.waitingTime[customer.number] = (self.currentTime - 
                                                     customer.entryTime)
                self.serviceTime[customer.number] = customer.serviceTime
                self.add_event(DEPART, self.currentTime + customer.serviceTime,
                               event.serverNumber)
            else:
                self.server[event.serverNumber] = IDLE
        else:
            print "Unknown event type"
            
    def which_queue(self):
        '''
        When an arrival occurs this methods is called if  there is an available
        server this method returns to the tuple of (queue,server) where queue
        represents the queue that the customer should join and server is one of
        the available servers if there is no available server, server value
        returned is None
        '''
        # Single server policy
        if self.queueing_mode == 'single':
            if self.sqList[0].isEmpty():
                for i in range(self.server_num):
                    if self.server[i] == IDLE:
                        self.server[i] = BUSY
                        return 0, i
            else:
                return 0, None
            return 0, None
        # COMPLETE CHOOSING RANDOM QUEUE
        elif self.queueing_mode == 'random':
            pass
        # COMPLETE CHOOSING SHORTEST QUEUE
        elif self.queueing_mode == 'shortest':
            pass

    def simulate(self, simulationLength):
        '''
        Simulates the system for simulationLength time units
        '''
        pgEventType = None
        if self.graphics_mode == 'on':
            self.display_init()
        while self.currentTime < simulationLength and pgEventType != QUIT:
            if self.graphics_mode == 'on':
                for pgEvent in pygame.event.get():
                    pgEventType = pgEvent.type
                self.clock.tick(self.framerate)
                self.draw_screen()
                self.screen.blit(self.background, (0,0))
                pygame.display.flip()
            event = self.get_event()
            self.process_event(event)

    def print_stat(self):
        '''
        Print statistics to stdout.
        '''
        for k in self.waitingTime:
            self.TIS[k] = self.waitingTime[k] + self.serviceTime[k]
        n1 = len(self.waitingTime)
        n2 = len(self.serviceTime)
        n3 = len(self.TIS)
        av1 = sum(self.waitingTime.values())/n1
        av2 = sum(self.serviceTime.values())/n2
        av3 = sum(self.TIS.values())/n3
        stdev1 = sqrt(sum([pow(self.waitingTime[i]-av1,2) for i in self.waitingTime])/(n1-1))
        stdev2 = sqrt(sum([pow(self.serviceTime[i]-av2,2) for i in self.serviceTime])/(n2-1))
        stdev3 = sqrt(sum([pow(self.TIS[i]-av3,2) for i in self.TIS])/(n3-1))
        print '\n'
        print 'Seed: ', self.seed
        print 'Mode', self.queueing_mode
        print 'Simulation ended at ', self.currentTime
        print '=========================\t STATISTICS',
        print ' \t ========================='
        print '\t\t\tObservations\tAverage\t\tStDev'
        print 'Waiting Time\t\t', n1, '\t\t', av1, '\t', stdev1
        print 'Service Time\t\t', n2, '\t\t', av2, '\t', stdev2
        print 'Time is System\t\t', n3, '\t\t', av3, '\t', stdev3

    def add_event(self, eventType, eventTime, serverNumber = None):
        '''
        Adds event to the eventTable
        '''        
        self.eventCounter += 1
        self.eventTable.push(Event(eventType, self.eventCounter, 
                                   eventTime, serverNumber))

    def get_event(self):
        '''
        Gets the first event in the event table
        '''        
        e = self.eventTable.pop()
        self.currentTime = e.eventTime
        return e

    def draw_screen(self):
        '''
        Draws the status of the system to the screen
        '''        
        # Draw queue and server rectangles
        for i in range(min(self.server_num, 50)):
            pygame.draw.rect(self.background, self.colors[self.server[i]],
                             self.rec[i])
        # Draw customer rectangles
        if self.queueing_mode == 'single':
            nrInQ = self.sqList[0].size()
            for i in range(46):
                rect = (690-i*15,305,self.cDimension[0],self.cDimension[1])
                if i<nrInQ:
                    pygame.draw.rect(self.background,self.colors['c'],rect)
                else:
                    pygame.draw.rect(self.background,self.colors['bg'],rect)
        else:
            for j in range(min(self.server_num, 50)):
                nrInQ = self.sqList[j].size()
                for i in range(46):
                    rect = (690-i*15,self.server_position[j],
                            self.cDimension[0], self.cDimension[1])
                    if i<nrInQ:
                        pygame.draw.rect(self.background,self.colors['c'],rect)
                    else:
                        pygame.draw.rect(self.background,self.colors['bg'],rect)

    def display_init(self):
        '''
        Initializes pygame related parameters.
        '''        
        pygame.init()
        # pygame display parameters
        self.cDimension = (10, 10)
        self.sDimension = (10,10)
        server_spacing = 550/min(self.server_num, 50)
        padding = (600-(min(self.server_num, 50) - 1)*server_spacing)/2
        self.server_position = [padding + i*server_spacing 
                                for i in range(min(self.server_num, 50))]
        self.rec = [(740, self.server_position[i], self.sDimension[0],
                     self.sDimension[1])
                    for i in range(min(self.server_num, 50))]
        self.framerate = 100
        self.colors = {'bg':(0,0,0),
                       'c':(0,0,200),
                       False:(0,255,0),
                       True:(255,0,0)}
        # end of pygame display parameters
        self.screenDimension = (800,600) 
        self.screen = pygame.display.set_mode(self.screenDimension)
        pygame.display.set_caption(__title__)
        self.background = self.screen.convert()
        self.clock = pygame.time.Clock()