def __init__(self): """ Initializes the tables. The q-values are initialized to a value of 10 since 10 seemed like an average q-value after the first 100000 iterations of training. The visits are initialized to zero since no actions have been taken yet. The same_locs table is initalized to all 0s except for the first column which is all 1s. The first column corresponds to the actions ['O', 'O', ..., 'O'] which will never change the locations of robots/stacks. Many times these tables are overwritten by csvs that have been saved after many iterations of training. Returns ------- None. """ num_states = (nCr(N_ROWS*N_COLS+1, N_ROBOTS) * nCr(N_ROWS*N_COLS+1, N_STACKS) * (N_ITEMS+1)**N_STACKS) num_actions = len(Actions().valid_actions)**N_ROBOTS self.qvals = np.ones((num_states, num_actions)) * (N_ROWS + N_COLS - 1) * N_STACKS self.visits = np.zeros((num_states, num_actions)) self.same_locs = np.concatenate((np.ones((1, num_states)), np.zeros((num_actions-1, num_states)))).transpose() self.performance = pd.DataFrame([], columns=['iters', 'score']) return
def enum(self): """ Enumerates the state by assigning a unique number to each state. First, enumerate the locations of the robots and multiply this value by the number of possible locations of stacks and possible orders values. Second, enumerate the locations of the stacks and multiply this value by the number of possible orders values. Last, enumerate the number of possible orders values. Add all these together to get the final enumeration of the state. Returns ------- int The enumeration of the state. """ ## enumerate the location of robots enum_robots = 0 locations = copy.deepcopy(self.valid_locations) for i in range(N_ROBOTS): idx = locations.index(self.robot_locs[i]) if i == N_ROBOTS - 1: enum_robots += idx else: locations = locations[1:] for j in range(idx): enum_robots += nCr(len(locations), N_ROBOTS - i - 1) locations = locations[1:] possible_stacks_orders = (nCr(N_ROWS * N_COLS + 1, N_STACKS) * (N_ITEMS+1)**N_STACKS) ## enumerate the locations of stacks enum_stacks = 0 locations = copy.deepcopy(self.valid_locations) for i in range(N_STACKS): idx = locations.index(self.stack_locs[i]) if i == N_STACKS - 1: enum_stacks += idx else: locations = locations[1:] for j in range(idx): enum_stacks += nCr(len(locations), N_STACKS - i - 1) locations = locations[1:] possible_orders = (N_ITEMS+1)**N_STACKS ## enumerate the order state variable enum_orders = 0 for i in range(N_STACKS): enum_orders += self.orders[i] * (N_ITEMS+1)**(N_STACKS-1-i) enum = (enum_robots * possible_stacks_orders + enum_stacks * possible_orders + enum_orders) return enum
def predict_cell(candidates, row, model, lef_data, std_cells): """ Use the trained model to choose the most probable cell from via groups. :param candidates: 2-via and 3-via groups that could make a cell :return: a tuple (chosen via group, predicted cell name) """ # possibly I can use the current method of testing the width of each cell # margin = 350 # dataset = np.ndarray(shape=(len(candidates), FEATURE_LEN), # dtype=np.float32) scores = [-100 for i in range(len(candidates))] for i in range(len(candidates)): if candidates[i] != -1: features = [] each_group = candidates[i] # width = std_cells[2] left_margin = std_cells[i][-1] # for left_margin in range(50, 800, 50): left_pt = [each_group[0][0][0] - left_margin, CELL_HEIGHT * row] # width = each_group[-1][0][0] - left_pt[0] + margin num_vias = len(each_group) features.append(num_vias) x_bound = left_pt[0] y_bound = left_pt[1] # NOTE: some cell has 4 vias # We suppose maximum vias in a cell is 4 for each_via in each_group: x_loc = each_via[0][0] - x_bound y_loc = each_via[0][1] - y_bound # features.append(x_loc) features.append(y_loc) # add via type features.append(each_via[3]) # if there are only two vias, then there are no via3 if num_vias < 4: temp = [-1 for i in range((4 - num_vias) * 2)] features.extend(temp) # add the distance between vias for i in range(num_vias - 1): for j in range(i + 1, num_vias): x_dist = each_group[j][0][0] - each_group[i][0][0] y_dist = each_group[j][0][1] - each_group[i][0][1] features.append(x_dist) features.append(y_dist) # add extra features in case of having less vias if num_vias < 4: if num_vias == 1: remain_dists = 2 * int(util.nCr(4, 2)) else: remain_dists = 2 * ( int(util.nCr(4, 2) - util.nCr(num_vias, 2))) temp = [0 for i in range(remain_dists)] features.extend(temp) # do predict dataset = np.array(features, dtype=np.int32) # print(dataset) X_test = dataset.reshape(1, FEATURE_LEN) result = model.decision_function(X_test) result = result[0] # print(each_group) # print(left_margin) print(labels[i]) print(features) print(result) # print() features = [] if result[i] == max(result): return candidates[i], i
def extract_comp(comp_name, lef_data, def_data, macro_via1_dict): """ Extract the features and label of each cell :param comp_name: name of the component :param lef_data: data parsed from LEF file. :param def_data: data parsed from DEF file. :param macro_via_dict: dictionary contains macro and via1 data :return: void """ # get info of the component and macro from DEF and LEF comp_info = def_data.components.comp_dict[comp_name] macro_name = comp_info.macro macro_info = lef_data.macro_dict[macro_name] macro_size = macro_info.info["SIZE"] scale = float(def_data.scale) # get the placement of the component from DEF file bottom_left_pt = comp_info.placed top_right_pt = [ bottom_left_pt[0] + int(macro_size[0] * scale), bottom_left_pt[1] + int(macro_size[1] * scale) ] corners = [bottom_left_pt, top_right_pt] # find the vias inside the component's area vias_in_comp = macro_via1_dict[comp_name] vias_draw = [] for pin in vias_in_comp: if pin != "MACRO": for each_via in vias_in_comp[pin]: each_via_loc = each_via[0] via_type = each_via[1] if inside_area(each_via_loc, corners): vias_draw.append((each_via_loc, via_type)) # sort the vias by x-coordinate vias_draw.sort(key=lambda x: x[0][0]) # crop the cell by the vias location # margin = 350 # left_pt = [vias_draw[0][0][0] - margin, bottom_left_pt[1]] # width = vias_draw[-1][0][0] - left_pt[0] + margin # height = macro_size[1] * scale # corners = [left_pt] # corners.append([left_pt[0] + width, left_pt[1] + height]) # get the pins from LEF data pins = [] for pin in macro_info.pin_dict.keys(): pin_name = pin.lower() if pin_name != 'gnd' and pin_name != 'vdd': pins.append(pin) left_pt = bottom_left_pt # build the features features = [] # number of vias num_vias = len(vias_draw) features.append(num_vias) x_bound = left_pt[0] y_bound = left_pt[1] # NOTE: some cell has 4 vias # We suppose maximum vias in a cell is 4 for each_via in vias_draw: x_loc = each_via[0][0] - x_bound y_loc = each_via[0][1] - y_bound # features.append(x_loc) features.append(y_loc) # determine the type of each via via_loc = each_via[0] # print(via_loc) pin_found = False for pin in pins: pin_data = macro_info.pin_dict[pin] pin_direction = pin_data.info["DIRECTION"].lower() layers = pin_data.info["PORT"].info["LAYER"] for layer in layers: for shape in layer.shapes: # scale the points corners = util.scalePts(shape.points, scale) corners = relocate_area(bottom_left_pt, corners) # print(corners) if inside_area(via_loc, corners): # print(pin) # print(pin_direction) pin_found = True if pin_direction == 'output': features.append(1) elif pin_direction == 'input': features.append(0) break if pin_found: break if not pin_found: features.append(-1) # if there are only two vias, then there are no via3 if num_vias < 4: # temp = [-1 for i in range((4 - num_vias) * 3)] # trial: only use num_vias, no x-coordinate and y-coordinate temp = [-1 for i in range((4 - num_vias) * 2)] features.extend(temp) # add the distance between vias for i in range(len(vias_draw) - 1): for j in range(i + 1, len(vias_draw)): x_dist = vias_draw[j][0][0] - vias_draw[i][0][0] y_dist = vias_draw[j][0][1] - vias_draw[i][0][1] features.append(x_dist) features.append(y_dist) # add extra features in case of having less vias if num_vias < 4: if num_vias == 1: remain_dists = 2 * int(util.nCr(4, 2)) else: remain_dists = 2 * (int(util.nCr(4, 2) - util.nCr(num_vias, 2))) temp = [0 for i in range(remain_dists)] features.extend(temp) # print(macro_name) # print(features) # print(len(features)) # add more features here label = macro_name return features, label
def extract_comp(comp_name, lef_data, def_data, macro_via1_dict): """ Extract the features and label of each cell :param comp_name: name of the component :param lef_data: data parsed from LEF file. :param def_data: data parsed from DEF file. :param macro_via_dict: dictionary contains macro and via1 data :return: void """ # get info of the component and macro from DEF and LEF comp_info = def_data.components.comp_dict[comp_name] macro_name = comp_info.macro macro_info = lef_data.macro_dict[macro_name] macro_size = macro_info.info["SIZE"] scale = float(def_data.scale) # get the placement of the component from DEF file bottom_left_pt = comp_info.placed top_right_pt = [bottom_left_pt[0] + int(macro_size[0] * scale), bottom_left_pt[1] + int(macro_size[1] * scale)] corners = [bottom_left_pt, top_right_pt] # find the vias inside the component's area vias_in_comp = macro_via1_dict[comp_name] vias_draw = [] for pin in vias_in_comp: if pin != "MACRO": for each_via in vias_in_comp[pin]: each_via_loc = each_via[0] via_type = each_via[1] if inside_area(each_via_loc, corners): vias_draw.append((each_via_loc, via_type)) # sort the vias by x-coordinate vias_draw.sort(key=lambda x: x[0][0]) # crop the cell by the vias location # margin = 350 # left_pt = [vias_draw[0][0][0] - margin, bottom_left_pt[1]] # width = vias_draw[-1][0][0] - left_pt[0] + margin # height = macro_size[1] * scale # corners = [left_pt] # corners.append([left_pt[0] + width, left_pt[1] + height]) # get the pins from LEF data pins = [] for pin in macro_info.pin_dict.keys(): pin_name = pin.lower() if pin_name != 'gnd' and pin_name != 'vdd': pins.append(pin) left_pt = bottom_left_pt # build the features features = [] # number of vias num_vias = len(vias_draw) features.append(num_vias) x_bound = left_pt[0] y_bound = left_pt[1] # NOTE: some cell has 4 vias # We suppose maximum vias in a cell is 4 for each_via in vias_draw: x_loc = each_via[0][0] - x_bound y_loc = each_via[0][1] - y_bound # features.append(x_loc) features.append(y_loc) # determine the type of each via via_loc = each_via[0] # print(via_loc) pin_found = False for pin in pins: pin_data = macro_info.pin_dict[pin] pin_direction = pin_data.info["DIRECTION"].lower() layers = pin_data.info["PORT"].info["LAYER"] for layer in layers: for shape in layer.shapes: # scale the points corners = util.scalePts(shape.points, scale) corners = relocate_area(bottom_left_pt, corners) # print(corners) if inside_area(via_loc, corners): # print(pin) # print(pin_direction) pin_found = True if pin_direction == 'output': features.append(1) elif pin_direction == 'input': features.append(0) break if pin_found: break if not pin_found: features.append(-1) # if there are only two vias, then there are no via3 if num_vias < 4: # temp = [-1 for i in range((4 - num_vias) * 3)] # trial: only use num_vias, no x-coordinate and y-coordinate temp = [-1 for i in range((4 - num_vias) * 2)] features.extend(temp) # add the distance between vias for i in range(len(vias_draw) - 1): for j in range(i + 1, len(vias_draw)): x_dist = vias_draw[j][0][0] - vias_draw[i][0][0] y_dist = vias_draw[j][0][1] - vias_draw[i][0][1] features.append(x_dist) features.append(y_dist) # add extra features in case of having less vias if num_vias < 4: if num_vias == 1: remain_dists = 2 * int(util.nCr(4, 2)) else: remain_dists = 2 * (int(util.nCr(4, 2) - util.nCr(num_vias, 2))) temp = [0 for i in range(remain_dists)] features.extend(temp) # print(macro_name) # print(features) # print(len(features)) # add more features here label = macro_name return features, label
def predict_cell(candidates, row, model, lef_data, std_cells): """ Use the trained model to choose the most probable cell from via groups. :param candidates: 2-via and 3-via groups that could make a cell :return: a tuple (chosen via group, predicted cell name) """ # possibly I can use the current method of testing the width of each cell # margin = 350 # dataset = np.ndarray(shape=(len(candidates), FEATURE_LEN), # dtype=np.float32) scores = [-100 for i in range(len(candidates))] for i in range(len(candidates)): if candidates[i] != -1: features = [] each_group = candidates[i] # width = std_cells[2] left_margin = std_cells[i][-1] # for left_margin in range(50, 800, 50): left_pt = [each_group[0][0][0] - left_margin, CELL_HEIGHT * row] # width = each_group[-1][0][0] - left_pt[0] + margin num_vias = len(each_group) features.append(num_vias) x_bound = left_pt[0] y_bound = left_pt[1] # NOTE: some cell has 4 vias # We suppose maximum vias in a cell is 4 for each_via in each_group: x_loc = each_via[0][0] - x_bound y_loc = each_via[0][1] - y_bound # features.append(x_loc) features.append(y_loc) # add via type features.append(each_via[3]) # if there are only two vias, then there are no via3 if num_vias < 4: temp = [-1 for i in range((4 - num_vias) * 2)] features.extend(temp) # add the distance between vias for i in range(num_vias - 1): for j in range(i + 1, num_vias): x_dist = each_group[j][0][0] - each_group[i][0][0] y_dist = each_group[j][0][1] - each_group[i][0][1] features.append(x_dist) features.append(y_dist) # add extra features in case of having less vias if num_vias < 4: if num_vias == 1: remain_dists = 2 * int(util.nCr(4, 2)) else: remain_dists = 2 * (int(util.nCr(4, 2) - util.nCr(num_vias, 2))) temp = [0 for i in range(remain_dists)] features.extend(temp) # do predict dataset = np.array(features, dtype=np.int32) # print(dataset) X_test = dataset.reshape(1, FEATURE_LEN) result = model.decision_function(X_test) result = result[0] # print(each_group) # print(left_margin) print(labels[i]) print(features) print(result) # print() features = [] if result[i] == max(result): return candidates[i], i