def a_star(starting_node, target_node, paths): """ A Star generic implementation (see https://en.wikipedia.org/wiki/A*_search_algorithm for more information) Finds a way from start to target by using the real cost of travelling and the heuristic values to determine a short path. :param starting_node: starting node :param target_node: target node :param paths: paths :return: ordered list of nodes leading to our goal. """ closed = list() # list that contains all visited nodes fringe = SortedList() # contains all found nodes fringe.append(starting_node) # append the starting node while True: if (len(fringe) == 0): # if the fringe is empty return None node = fringe.pop(0) if not any(node.id == it.id for it in closed): # if the current node is not in our closed list do: # print("Current Node= {}, Fringe={}".format(node,fringe)) - uncomment to see how it works! if (goal_check(node, target_node)): # if the current node is our target find the path return find_solution(node) else: # else find all neighboring nodes of the current node and add them to the fringe, finally add the curr node to closed. connected_nodes = get_connected_nodes(node, paths) for connected_node in connected_nodes: fringe.add(connected_node) closed.append(node) else: print("skipped node={}".format(node))
def get_top_pageranks(inlinks, outlinks, b, n=50, iters=20): """ >>> inlinks = SortedDict({'a': ['c'], 'b': set(['a']), 'c': set(['a', 'b'])}) >>> outlinks = SortedDict({'a': ['b', 'c'], 'b': set(['c']), 'c': set(['a'])}) >>> res = get_top_pageranks(inlinks, outlinks, b=.5, n=2, iters=1) >>> len(res) 2 >>> res[0] # doctest:+ELLIPSIS ('a', 0.6666... """ res = [] urls = SortedList() for out in outlinks: urls.append(out) pagerank = compute_pagerank(urls, inlinks, outlinks, b, iters) for num in range(n): temp = 0 temp_u = '' for u in pagerank: if temp < pagerank[u] and u not in res: temp = pagerank[u] temp_u = u res.append((temp_u, temp)) pagerank.pop(temp_u) return res
def join_sections(sections): if isinstance(sections, SortedList): result_sections = SortedList(key=attrgetter("start_address")) else: result_sections = [] prev_section = Section() while sections: section = sections.pop(0) if not isinstance(section, Section): raise TypeError("'{}' is not a 'Section' instance", section) if section.start_address == prev_section.start_address + prev_section.length and result_sections: last_segment = result_sections[-1] last_segment.data.extend(section.data) last_segment.length += section.length else: # Create a new section. if isinstance(sections, SortedList): result_sections.add( Section(section.start_address, section.data)) else: result_sections.append( Section(section.start_address, section.data)) prev_section = section if result_sections: return result_sections else: if isinstance(sections, SortedList): return SortedList(key=attrgetter("start_address")) else: return []
def test_append(): slt = SortedList(load=17) slt.append(0) for val in range(1, 1000): slt.append(val) slt._check()
class MySorted: def __init__(self): self.elements = SortedList() def index(self, val): if not self.elements or self.elements[0] >= val: return 0 elif self.elements[-1] <= val: return len(self.elements) return self.elements.index(val) def append(self, val): self.elements.append(val) def __len__(self): return len(self.elements)
def generateTestData(queryPositivePercentage, sampleSize, maxUniverse): uncompressedList = [] queryList = SortedList([]) negativeList = [] samplePercentage = sampleSize / maxUniverse * 100 random.seed(datetime.now()) for x in range(1, maxUniverse): if (random.randint(1, 100) <= samplePercentage): uncompressedList.append(x) if (random.randint(1, 100) <= queryPositivePercentage): queryList.append(x) elif (len(negativeList) > 0): # you add some random element from the negative list randomIndex = random.randrange(len(negativeList)) queryList.add(negativeList.pop(randomIndex)) else: negativeList.append(x) return (uncompressedList, list(queryList.islice(0, len(queryList))))
def test_append_valueerror(): slt = SortedList(range(100)) slt.append(5)
class Genetic_algorithm(object): def __init__(self, goal: object, goal_score: int, max_number_of_children: int, population_limit: int, crossover_chromosoma_probability: float, tournament_size: int, mutation_probability: float, mutation_chromosoma_probability: float, max_pixel_value: int, strongest_rate=0.2): self.__goal = goal self.__goal_score = goal_score self.__number_of_chromosomes = len(goal) self.__population = SortedList() self.__new_population = queue.Queue() self.__population_limit = population_limit self.__tournament_size = tournament_size self.__crossover_chromosoma_probability = crossover_chromosoma_probability self.__mutation_probability = mutation_probability self.__mutation_chromosoma_probability = mutation_chromosoma_probability self.__strongest_limit = strongest_rate * population_limit self.__max_number_of_children = max_number_of_children self.__high_boundary_of_pixel = max_pixel_value + 1 def run_algorithm(self): self.__generate_initial_population() self.__recombination() is_solved = self.__evaluate() while not is_solved: winners = self.__selection() self.__new_population = queue.Queue(self.__crossover(winners)) self.__mutation() self.__recombination() is_solved = self.__evaluate() def __selection_tournament(self): selected_individuals = queue.Queue( random.sample(self.__population[:self.__strongest_limit], self.__tournament_size)) winners = queue.Queue() while (len(selected_individuals) > 1): individual_A = selected_individuals.get() individual_B = selected_individuals.get() if (individual_A > individual_B): winners.put(individual_A) else: winners.put(individual_B) return winners def __crossover(self, winners): winners_shuffle = queue.Queue( random.sample(self.__population[:self.__strongest_limit], self.__tournament_size)) while (not winners_shuffle.empty()): individual_A = winners_shuffle.get() individual_B = winners_shuffle.get() number_of_children = random.uniform(0, self.__max_number_of_children) children = list() [ children.update( self.__crossover_individuals(individual_A, individual_B)) in range(number_of_children) ] return children def __crossover_individuals(self, individual_A, individual_B): children_list = list() for chromosoma_A, chromosoma_B in zip(individual_A.get_dna(), individual_B.get_dna()): is_crossover = random.uniform( 0, 1) < self.__crossover_chromosoma_probability if is_crossover: new_chromosoma = (chromosoma_A + chromosoma_B) * 0.5 children_list.append(new_chromosoma) else: chromosoma_to_add = chromosoma_A if random.uniform( 0, 1) < 0.5 else chromosoma_B children_list.append(chromosoma_to_add) return Individual(np.array(children_list)) def __mutation(self): for individual in self.__population: is_mutation = random.uniform( 0, self.__high_boundary_of_pixel) < self.__mutation_probability if is_mutation: self.__new_population.put(self.__mutate_individual(individual)) def __mutate_individual(self, individual): mutated_individual = list() for chromosoma in enumerate(individual.get_dna()): is_mutation_chromosoma = random.uniform( 0, 1) < self.__mutation_chromosoma_probability if is_mutation_chromosoma: mutated_individual.append( random.uniform(0, self.__high_boundary_of_pixel)) else: mutated_individual.append(chromosoma) return Individual(np.array(mutated_individual)) def __recombination(self): while not self.__new_population.empty(): new_individual = self.__new_population.get() new_individual.set_score( self.__evaluate_individual(new_individual)) self.__population.append(new_individual) self.__population = self.__population[self.__population_limit:] def __evaluate_individual(self, individual): return np.sum(np.abs(np.subtract(individual.get_dna(), self.__goal))) def __evaluate(self): return self.__population[0].get_score() < self.__goal_score def __generate_initial_population(self): for i in range(self.__population_limit): new_dna = np.random.randint(self.__max_pixel_value, size=self.__image_goal.shape) new_individual = Individual(new_dna) self.__new_population.put(new_individual)
class Construe(object): """ This class implements the **kardioml.segmentation.teijeiro.* algorithm allowing fine-grained control of the steps of the algorithm. """ def __init__(self, root_node, K): """ Initializes a new algorithm execution, receiving as arguments the root node for the exploration and the K parameter, which determines the exploratory nature of the algorithm. Instance Properties ------------------- K: Exploration parameter. successors: Dictionary storing the successor generator of each node. last_time: Interpretation time of the most advanced interpretation generated so far. open: Sorted list of the open nodes, that can still be expanded. closed: Sorted list of closed nodes. best: When a node satisfies the *goal()* function, this attribute is assigned to that node. While the finished() method returns False, this attribute may be refined with new better interpretations. """ assert K > 0 self.K = K self.root = root_node self.successors = weakref.WeakKeyDictionary() root_succ = PredictableIter(reasoning.firm_succ(root_node)) if not root_succ.hasnext(): raise ValueError('The root node does not have valid successors') self.successors[root_node] = root_succ self.last_time = root_node.time_point ocov, scov, nhyp = valuation(root_node) heur = Heuristic(ocov, scov, -self.last_time, nhyp) self.open = SortedList([Node(heur, root_node)], key=attrgetter('h')) self.closed = SortedList(key=attrgetter('h')) self.best = None def _update_closed(self, newclosed): """ Updates the *closed* list after an iteration of the algorithm. All closed interpretations but the best one are removed from this list. """ if not newclosed: return tmplst = SortedList(key=attrgetter('h')) for lst in (newclosed, self.closed): for (ocov, scov, ntime, nhyp), n in lst: if -ntime < self.last_time: ocov, scov, nhyp = valuation(n, self.last_time) tmplst.add(Node(Heuristic(ocov, scov, ntime, nhyp), n)) self.closed.clear() self.closed.append(tmplst.pop(0)) def step(self, filt=lambda _: True): """ Performs a new step of the algorithm, by continuing the K-best nodes satisfying the *filt* function one step. Parameters ---------- filt: Boolean function that receives an element of the open list and decides if the node can be expanded in this iteration. The first K nodes satisfying this filter are expanded. """ newopen = [] newclosed = [] ancestors = set() optimal = False for _ in range(self.K): node = next((n for n in self.open if filt(n) and not (optimal and n.node in ancestors)), None) # The search stops if no nodes can be expanded or if, being in an # optimal context, we need to expand a non-optimal node. if node is None or (optimal and node.h.ocov > 0.0): break self.open.remove(node) # Go a step further nxt = self.successors[node.node].next() self.successors[nxt] = PredictableIter(reasoning.firm_succ(nxt)) nxtime = nxt.time_point if nxtime > self.last_time: self.last_time = nxtime ocov, scov, nhyp = valuation(nxt, nxtime) nxt = Node(Heuristic(ocov, scov, -nxtime, nhyp), nxt) # Optimality is determined by the coverage of the successors. optimal = optimal or ocov == 0.0 # Reorganize the open and closed list. for n in (node, nxt): if self.successors[n.node].hasnext(): newopen.append(n) reasoning.save_hierarchy(n.node, ancestors) else: newclosed.append(n) if ( n is nxt and n.h.ocov == 0.0 and goal(n.node) and (self.best is None or n.h < self.best.h) ): self.best = n for node in newopen: self.open.add(node) # The closed list is recalculated by keeping only the best one. self._update_closed(newclosed) if not self.open: if not self.closed: raise ValueError('Could not find a complete interpretation.') self.best = min(self.closed) def prune(self): """ Perform a pruning operation by limiting the size of the *open* list only to the K best. """ # Now we get the best nodes with a common valuation. newopened = SortedList(key=attrgetter('h')) for h, node in self.open: ocov, scov, nhyp = valuation(node, self.last_time) newopened.add(Node(Heuristic(ocov, scov, h.time, nhyp), node)) self.open = newopened n = min(len(self.open), self.K) if not reasoning.SAVE_TREE: # We track all interesting nodes in the hierarchy. saved = set() stop = set() for i in range(n): node = self.open[i].node reasoning.save_hierarchy(node, saved) stop.add(node) mrg = reasoning._MERGED.get(node) if mrg is not None: reasoning.save_hierarchy(mrg, saved) stop.add(mrg) for _, node in self.closed: reasoning.save_hierarchy(node, saved) if self.best is not None: reasoning.save_hierarchy(self.best.node, saved) # And we prune all nodes outside the saved hierarchy stack = [self.root] while stack: node = stack.pop() if node not in saved: node.discard('Sacrificed interpretation') elif node not in stop: stack.extend(node.child) del self.open[n:] # We also clear the reasoning cache, since some interpretations cannot # be eligible for merging anymore. if self.open: earliestime = min(n.past_metrics.time for _, n in self.open) reasoning.clear_cache(earliestime) def finished(self): """ Checks if the searching procedure is finished, that is, more iterations, even if possible, will probably not lead to better interpretations that the best one. This is considered true if in the open list there are no partial covers with less hypotheses than the current best interpretation and that are not ancestors of the current best interpretation. """ return self.best is not None and all( self.best.node.is_ancestor(n.node) for n in self.open if n.h.ocov == 0.0 and n.h.nhyp < self.best.h.nhyp )
class GreedyTaskQueue(TaskQueue): """Describes a greedy task queue, which prioritizes tasks with the highest number of cores. :ivar int total_cores: if the cores on a task is None, we assume it is going to require this many cores. :ivar dict[int, list[Task]] tasks_by_core: a lookup for remaining tasks, where the key is the number of cores the task requires. :ivar SortedList[int] sorted_keys: the keys for tasks_by_core in ascending order. :ivar bool expecting_more_tasks: if True, we expect that add_task will be called in the (near) future, hence we always return True from have_more_tasks :ivar int _len: the length of this queue """ def __init__(self, total_cores: int): """Initializes an empty task queue.""" self.total_cores = total_cores self.tasks_by_core = dict() self.sorted_keys = SortedList() self.expecting_more_tasks = False self._len = 0 def flatten(self) -> typing.List[Task]: """Returns this task queue as a list of tasks. """ res = [] for v in self.tasks_by_core.values(): res.extend(v) return res def set_total_cores(self, total_cores): old_total = self.total_cores self.total_cores = total_cores if len(self.sorted_keys) == 0: return if old_total < total_cores: flat = self.flatten() self.sorted_keys = SortedList() self.tasks_by_core = dict() self._len = 0 self.add_tasks(flat) return arrs = [] while self.sorted_keys[-1] > self.total_cores: k = self.sorted_keys.pop() arrs.append(self.tasks_by_core[k]) del self.tasks_by_core[k] if not self.sorted_keys: self.sorted_keys.append(self.total_cores) self.tasks_by_core[self.total_cores] = [] last = self.tasks_by_core[self.sorted_keys[-1]] for arr in arrs: last.extend(arr) def add_task(self, task: Task) -> None: """Adds the given task to this queue.""" cores_req = self.total_cores if task.cores is not None: cores_req = min(task.cores, self.total_cores) arr = self.tasks_by_core.get(cores_req) if arr is None: arr = [] self.tasks_by_core[cores_req] = arr self.sorted_keys.add(cores_req) arr.append(task) self._len += 1 def add_tasks(self, tasks: typing.Iterable[Task]) -> None: """Adds all the specified tasks to this queue.""" for task in tasks: self.add_task(task) def get_next_task(self, cores: int): prev = None for k in self.sorted_keys: if k > cores: break prev = k if prev is None: return None arr = self.tasks_by_core[prev] res = arr.pop() self._len -= 1 if not arr: del self.tasks_by_core[prev] self.sorted_keys.remove(prev) return res def have_more_tasks(self): return not self.expecting_more_tasks and len(self.sorted_keys) > 0 def __len__(self): return self._len