def __history_dependent_iter_simulate(self, node, iterations, step_profile): ''' Simulate from the given node for the given number of iterations. (Internal function for history-dependent simulations only.) The results are implemented into the tree. Note that the crunching for this is done synchronously, i.e. in the currrent thread. This returns a generator that yields all the nodes one-by-one, from the initial node to the final one. A step profile may be passed to be used with the step function. ''' path = node.make_containing_path() history_browser = garlicsim.synchronous_crunching.HistoryBrowser( path, tail_node=node ) iterator = self.simpack_grokker.get_step_iterator(history_browser, step_profile) finite_iterator = cute_iter_tools.shorten(iterator, iterations) finite_iterator_with_lock = cute_iter_tools.iter_with( finite_iterator, self.tree.lock.write ) current_node = node yield current_node try: for current_state in finite_iterator_with_lock: current_node = self.tree.add_state(current_state, parent=current_node, step_profile=step_profile) history_browser.tail_node = current_node history_browser.path = current_node.make_containing_path() # Similarly to the `__history_dependent_simulate` method, here # we also need to recreate the path. But in this case we need # to do it not only on the first run, but on *each* run of the # loop, because this is a generator, and the user may wreak # havoc with the tree between `yield`s, causing our original # path not to lead to the `tail_node` anymore. # todo optimize: The fact we recreate a path every time might # be costly. yield current_node except garlicsim.misc.WorldEnded: self.tree.make_end(current_node, step_profile)
def __non_history_dependent_iter_simulate(self, node, iterations, step_profile=None): ''' Simulate from the given node for the given number of iterations. (Internal function for non-history-dependent simulations only.) The results are implemented into the tree. Note that the crunching for this is done synchronously, i.e. in the currrent thread. This returns a generator that yields all the nodes one-by-one, from the initial node to the final one. A step profile may be passed to be used with the step function. ''' if step_profile is None: step_profile = garlicsim.misc.StepProfile() state = node.state iterator = self.simpack_grokker.step_generator(state, step_profile) finite_iterator = cute_iter_tools.shorten(iterator, iterations) finite_iterator_with_lock = cute_iter_tools.iter_with( finite_iterator, self.tree.lock.write ) current_node = node yield current_node try: for current_state in finite_iterator_with_lock: current_node = self.tree.add_state(current_state, parent=current_node, step_profile=step_profile) yield current_node except garlicsim.misc.WorldEnd: self.tree.make_end(current_node, step_profile)