def find_placement(pieces, resistors_as_components, cost_type): """ Given a list of |pieces|, returns a placement of the pieces that requires comparatively small wiring. Finding the absolute best placement is too expensive. If the |pieces| cannot be placed so as to fit on a protoboard, returns None with a cost of float('inf'). """ assert isinstance(pieces, list), 'pieces must be a list' assert all(isinstance(piece, Circuit_Piece) for piece in pieces), ('all ' 'items in pieces must be Circuit_Pieces') pieces = deepcopy(pieces) if len(pieces) == 0: return [], 0 # order pieces in decreasing number of nodes pieces.sort(key=lambda piece: -len(piece.nodes)) queue = Queue() def add_to_queue(piece): if piece in pieces: queue.push(piece) pieces.remove(piece) placement = [] placement_cost = float('inf') while pieces: add_to_queue(pieces[0]) while queue: current_piece = queue.pop() # try inserting the current piece at all possible indicies in the current # placement, consider both regular and inverted piece best_placement = None best_placement_cost = float('inf') # all indicies in which the piece can be inserted for i in xrange(len(placement) + 1): # both regular and inverted piece for piece in set([current_piece, current_piece.inverted()]): for top_left_row in piece.possible_top_left_rows: piece.top_left_row = top_left_row new_placement = deepcopy(placement) new_placement.insert(i, piece) new_placement_cost = cost(new_placement, resistors_as_components, cost_type) if new_placement_cost < best_placement_cost: best_placement = deepcopy(new_placement) best_placement_cost = new_placement_cost if best_placement is None: return None, float('inf') placement = best_placement placement_cost = best_placement_cost # add pieces connected to this piece to the queue for piece in reduce( list.__add__, [[piece for piece in pieces if node in piece.nodes] for node in current_piece.nodes], []): add_to_queue(piece) return placement, placement_cost
def find_placement(pieces, resistors_as_components, cost_type): """ Given a list of |pieces|, returns a placement of the pieces that requires comparatively small wiring. Finding the absolute best placement is too expensive. If the |pieces| cannot be placed so as to fit on a protoboard, returns None with a cost of float('inf'). """ assert isinstance(pieces, list), 'pieces must be a list' assert all(isinstance(piece, Circuit_Piece) for piece in pieces), ('all ' 'items in pieces must be Circuit_Pieces') pieces = deepcopy(pieces) if len(pieces) == 0: return [], 0 # order pieces in decreasing number of nodes pieces.sort(key=lambda piece: -len(piece.nodes)) queue = Queue() def add_to_queue(piece): if piece in pieces: queue.push(piece) pieces.remove(piece) placement = [] placement_cost = float('inf') while pieces: add_to_queue(pieces[0]) while queue: current_piece = queue.pop() # try inserting the current piece at all possible indicies in the current # placement, consider both regular and inverted piece best_placement = None best_placement_cost = float('inf') # all indicies in which the piece can be inserted for i in xrange(len(placement) + 1): # both regular and inverted piece for piece in set([current_piece, current_piece.inverted()]): for top_left_row in piece.possible_top_left_rows: piece.top_left_row = top_left_row new_placement = deepcopy(placement) new_placement.insert(i, piece) new_placement_cost = cost(new_placement, resistors_as_components, cost_type) if new_placement_cost < best_placement_cost: best_placement = deepcopy(new_placement) best_placement_cost = new_placement_cost if best_placement is None: return None, float('inf') placement = best_placement placement_cost = best_placement_cost # add pieces connected to this piece to the queue for piece in reduce(list.__add__, [[piece for piece in pieces if node in piece.nodes] for node in current_piece.nodes], []): add_to_queue(piece) return placement, placement_cost
def closest_vertex(self, frm, target_list): """ closest_vertex(frm, target_list) -> id Uses bfs-like algorithm to find closest vertex to frm in target_list """ if frm in target_list: return frm target_list = set(target_list) visited = set([frm]) parent = {} q = Queue() q.push(frm) while 1: try: current = q.pop() except q.EmptyQueue: raise GraphException("no vertices reachable: %s %s" % (frm, list(target_list))) efrom = self.edges_from(current) for (to, eid) in efrom: if to in target_list: return to if to not in visited: parent[to] = current q.push(to) visited.add(to)
def bfs(self, frm): """ bfs(frm:id type) -> dict(id type) Perform Breadth-First-Search and return a dict of parent id Keyword arguments: frm -- 'immutable' vertex id """ visited = set([frm]) parent = {} q = Queue() q.push(frm) while 1: try: current = q.pop() except q.EmptyQueue: break efrom = self.edges_from(current) for (to, eid) in efrom: if to not in visited: parent[to] = current q.push(to) visited.add(to) return parent