Example #1
0
 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)
Example #2
0
    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)